无论如何,是否可以直接将已知数量的字节读取到 std::string 中,而无需创建临时缓冲区来执行此操作?
例如,目前我可以通过
boost::uint16_t len;
is.read((char*)&len, 2);
char *tmpStr = new char[len];
is.read(tmpStr, len);
std::string str(tmpStr, len);
delete[] tmpStr;
std::string
有一个resize
你可以使用的函数,或者一个可以做同样事情的构造函数:
boost::uint16_t len;
is.read((char*)&len, 2);
std::string str(len, '\0');
is.read(&str[0], len);
这是未经测试的,我不知道是否要求字符串具有连续存储。
您可以使用 copy_n 和 insert_iterator 的组合
void test_1816319()
{
static char const* fname = "test_1816319.bin";
std::ofstream ofs(fname, std::ios::binary);
ofs.write("\x2\x0", 2);
ofs.write("ab", 2);
ofs.close();
std::ifstream ifs(fname, std::ios::binary);
std::string s;
size_t n = 0;
ifs.read((char*)&n, 2);
std::istream_iterator<char> isi(ifs), isiend;
std::copy_n(isi, n, std::insert_iterator<std::string>(s, s.begin()));
ifs.close();
_unlink(fname);
std::cout << s << std::endl;
}
没有复制,没有黑客,没有溢出的可能性,没有未定义的行为。
您可以使用 getline 之类的东西:
#include <iostream>
#include <string>
using namespace std;
int main () {
string str;
getline (cin,str,' ');
}
我会使用向量作为缓冲区。
boost::uint16_t len;
is.read((char*)&len, 2); // Note if this file was saved from a different architecture
// then endianness of these two bytes may be reversed.
std::vector buffer(len); // uninitialized.
is.read(&buffer[0], len);
std::string str(buffer.begin(),buffer.end());
虽然您可能会使用字符串作为缓冲区(如 GMan 所述)。标准不能保证字符串成员位于连续的位置(因此请检查您当前的实现并在移植到另一个编译器/平台时添加需要检查的重要注释)。
您是在优化代码长度还是试图在此处为自己保存一份副本?临时缓冲区有什么问题?
我认为你实际上是在规避字符串的保护,试图直接写那样做。如果您担心复制到 std::string 的性能,因为您已经确定它会以某种方式影响应用程序的性能,我会直接使用 char*。
编辑:做更多的寻找...... 从 char* 初始化 std::string 而不复制
在第二个答案中,它非常明确地表明您无法实现您想要实现的目标(即填充 std::string 而不对 char* 进行迭代以进行复制。)
看看你的加载例程(也许在这里发布?)并最小化分配:new 和 delete 当然不是免费的,所以如果你不必不断地重新创建缓冲区,你至少可以节省一些时间。我总是发现通过将缓冲区设置为 0 或 null 以在每次迭代时终止数组的第一个索引来擦除它是有帮助的,但是一旦您对自己的算法有信心,您可能会出于性能考虑迅速消除该代码。
一个简单的方法是:
std::istream& data
const size_t dataSize(static_cast<size_t>(data.rdbuf()->in_avail()));
std::string content;
content.reserve( dataSize);
data.read(&content[0], dataSize);