如何为std :: string对象预先分配内存?

我需要将一个文件复制到一个string中。 我需要预先分配该string对象的内存,并直接将文件内容读入该string的内存中?

std::string 也有一个.reserve方法 。

这本身并不是一个答案,作为对其他一些答案的一种评论/总结/比较(以及为什么我推荐了代码样式的快速演示@Johannes – litb给出了在他的答案)。 由于@sbi发布了一个看起来不错的替代scheme,并且(特别是)避免了读入stringstream中的额外拷贝,然后使用.str()成员来获得一个string,所以我决定写一个两者的快速比较:

[编辑:我用@Tyler McHenry的基于istreambuf_iterator的代码添加了第三个testing用例,并添加了一行来打印出每个string的长度,以确保优化器不会优化读取,因为结果从未使用过。]

[编辑2:现在,马丁·约克的代码也被添加了…]

 #include <fstream> #include <sstream> #include <string> #include <iostream> #include <iterator> #include <time.h> int main() { std::ostringstream os; std::ifstream file("equivs2.txt"); clock_t start1 = clock(); os << file.rdbuf(); std::string s = os.str(); clock_t stop1 = clock(); std::cout << "\ns.length() = " << s.length(); std::string s2; clock_t start2 = clock(); file.seekg( 0, std::ios_base::end ); const std::streampos pos = file.tellg(); file.seekg(0, std::ios_base::beg); if( pos!=std::streampos(-1) ) s2.reserve(static_cast<std::string::size_type>(pos)); s2.assign(std::istream_iterator<char>(file), std::istream_iterator<char>()); clock_t stop2 = clock(); std::cout << "\ns2.length = " << s2.length(); file.clear(); std::string s3; clock_t start3 = clock(); file.seekg(0, std::ios::end); s3.reserve(file.tellg()); file.seekg(0, std::ios::beg); s3.assign((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>()); clock_t stop3 = clock(); std::cout << "\ns3.length = " << s3.length(); // New Test std::string s4; clock_t start4 = clock(); file.seekg(0, std::ios::end); s4.resize(file.tellg()); file.seekg(0, std::ios::beg); file.read(&s4[0], s4.length()); clock_t stop4 = clock(); std::cout << "\ns4.length = " << s3.length(); std::cout << "\nTime using rdbuf: " << stop1 - start1; std::cout << "\nTime using istream_iterator: " << stop2- start2; std::cout << "\nTime using istreambuf_iterator: " << stop3 - start3; std::cout << "\nTime using read: " << stop4 - start4; return 0; } 

现在令人印象深刻的部分 – 结果。 首先用VC ++(如果有人关心,Martin的代码是足够快的,我增加了文件的大小,以获得一个有意义的时间):

s.length()= 7669436
s2.length = 6390688
s3.length = 7669436
s4.length = 7669436
使用rdbuf的时间:184
使用istream_iterator的时间:1332
使用istreambuf_iterator的时间:249
时间使用阅读:48

然后用gcc(cygwin):

s.length()= 8278035
s2.length = 6390689
s3.length = 8278035
s4.length = 8278035
使用rdbuf的时间:62
使用istream_iterator的时间:2199
使用istreambuf_iterator的时间:156
时间使用阅读:16

[编辑结束 – 结论依然存在,尽pipe获胜者已经改变 – 马丁的代码显然是最快的。 ]

结果是相当一致的,就其中最快和最慢而言。 唯一的不一致是一个比另一个更快或更慢。 尽pipe位置相同,但gcc的速度差异大于VC ++。

这应该是你需要的一切:

 ostringstream os; ifstream file("name.txt"); os << file.rdbuf(); string s = os.str(); 

这从file读取字符并将其插入到stringstream中。 之后它得到在幕后创build的string。 请注意,我陷入了下面的陷阱:使用提取操作符将跳过初始空格。 你必须使用上面的插入操作符,或使用noskipws操纵器:

 // Beware, skips initial whitespace! file >> os.rdbuf(); // This does not skip it file >> noskipws >> os.rdbuf(); 

这些函数被描述为逐个字符地读取数据stream(尽pipe不确定在这里有什么优化是可能的),但是我没有计时来确定它们的速度。

只是为了好玩,这是另一种方式来做到这一点:

 // Beware, brain-compiled code ahead! std::ifstream ifs( /* ... */ ); if( !ifs.good() ) return; // whatever std::string str; ifs.seekg( 0, std::ios_base::end ); const std::streampos pos = ifs.tellg(); ifs.seekg( 0, std::ios_base::beg ); if( pos!=std::streampos(-1) ) // can get stream size? str.reserve(static_cast<std::string::size_type>(pos)); str.assign( std::istream_iterator<char>(ifs) , std::istream_iterator<char>() ); 

我希望我没有把它吹得太厉害。

的std :: string ::储备()

的std ::函数getline()

看来你是问如何做一个CString :: GetBuffer,ReleaseBuffertypes的操作与std :: string。

我不知道有什么方法可以直接做到这一点,一个简单的方法是创build一个原始的C风格缓冲区,读入缓冲区,然后使用assign或者其他方法将缓冲区复制到std :: string。 当然,你将不得不担心缓冲区溢出问题等,我也会使用std :: autoptr来pipe理原始缓冲区指针,以便在exception等情况下取消分配。这比使用stringstream等简单一点。我可以提供一个例子,如果需要。

德文Ellingson