直接从std :: istream读取到std :: string

Fir*_*cer 13 c++ iostream stdstring

无论如何都要读取已知的字节数,直接读入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;
Run Code Online (Sandbox Code Playgroud)

GMa*_*ckG 11

std::string有一个resize你可以使用的函数,或者一个会做同样的构造函数:

boost::uint16_t len;
is.read((char*)&len, 2);

std::string str(len, '\0');
is.read(&str[0], len);
Run Code Online (Sandbox Code Playgroud)

这是未经测试的,我不知道是否要求字符串具有连续存储.

  • 它们没有被定义为向量,但21.3.4/1确实意味着连续存储.然而,关于该特定部分存在混淆和缺陷报告,我不确定当前的共识是什么,也不确定具体的可解释性. (5认同)
  • 在C++ 11,21.4.1/5中,它说"basic_string对象中的类似char的对象应该连续存储". (4认同)
  • @Roger.我不同意21.3.4/1意味着连续存储.存在c_str()和data()意味着它,但仅仅因为有效的实现需要连续的存储来实现它们.我相信该标准的下一个版本也消除了这种情况的歧义. (2认同)

dex*_*ack 6

您可以使用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;
}
Run Code Online (Sandbox Code Playgroud)

没有复制,没有黑客,没有超支的可能性,没有未定义的行为.