C++ 是否建议std::将字符串移动到将被覆盖的容器中?
我有以下代码C++ 是否建议std::将字符串移动到将被覆盖的容器中?,c++,c++11,move-semantics,C++,C++11,Move Semantics,我有以下代码 std::vector<std::string> lines; std::string currentLine; while(std::getline(std::cin, currentLine)) { // // option 1 // lines.push_back(std::move(currentLine)); // // option 2 // lines.push_back(currentLine); } std::矢量线; std::
std::vector<std::string> lines;
std::string currentLine;
while(std::getline(std::cin, currentLine)) {
// // option 1
// lines.push_back(std::move(currentLine));
// // option 2
// lines.push_back(currentLine);
}
std::矢量线;
std::字符串currentLine;
while(std::getline(std::cin,currentLine)){
////选项1
//行。向后推(标准::移动(当前行));
////选项2
//线路。推回(当前线路);
}
我认为两者的成本不同
currentLine
,使得getline
需要为字符串分配一个新的缓冲区。但它将使用向量的缓冲区getline
能够重用缓冲区,并需要为向量内字符串分配新的缓冲区在这种情况下,有没有“更好”的方法?编译器能否更有效地优化一种或另一种方法?还是有聪明的字符串实现可以使一种方法比另一种方法更有效?鉴于短字符串优化的流行,我的直接猜测是,在许多情况下,这一切都不会有任何区别——对于SSO,移动最终会复制包含的数据(即使源是右值,也可以作为移动源) 在你给出的这两个版本中,我想我倾向于选择非移动版本,但我怀疑这两种版本都会有很大的不同。鉴于(大多数情况下)你会在移动后立即重新使用源代码,我怀疑移动是否真的会带来很多好处(即使最好)。假设不涉及SSO,您的选择是在向量中创建一个新字符串来保存您读取的字符串的副本,或者从您读取的字符串移动,并(本质上)创建一个新字符串来保存下一次迭代中的下一行。无论哪种方式,代价都很高(分配一个缓冲区来保存字符串,将数据复制到该缓冲区)这两种情况都差不多 至于“是否有更好的方法”这一点,我至少可以想到两种可能性。最明显的方法是内存映射文件,然后遍历该缓冲区,找到行尾,然后使用
emplace\u back
直接从缓冲区中的数据在向量中创建字符串,而不使用任何中间字符串
这确实有内存映射未标准化的一个小缺点——如果您不能忍受这种不可移植性,您可以将整个文件读入缓冲区,而不是内存映射
之后的下一个可能性是创建一个类,该类具有一个类似const string的接口,该接口只维护一个指向大缓冲区中数据的指针,而不是复制它(例如,CLang使用类似的东西)。这通常会减少总分配、堆碎片等,但如果以后需要修改字符串,它不太可能有多大用处。如果我要选择,我会选择选项二,因为
currentLine
(我想)通常比需要的大。(一份拷贝就不会共享它的容量
)如果有的话,选项2允许currentLine
增长,直到它足够大以容纳看到的最大值。如果看到的最大值不是最后看到的值,那么对std::getline
的额外调用将不需要重新分配currentLine
的缓冲区。如果性能是一个问题,我将执行移动,一个然后重新调整currentLine
的大小,使其与刚刚移动的字符串大小相同。除非你打字速度非常快,否则我认为这不会有任何区别。:-)只是开玩笑而已。我也喜欢2。在计算分配数量方面做得很好。短字符串优化有多流行?至少我不记得在VC++中见过它(虽然没有检查过最新版本或其他地方),VC++已经做SSO有相当一段时间了。我相信使用gcc取决于您使用哪个库——有些人使用它,有些人不使用(但我不太确定哪些确切的库使用/不使用)。VC++使用SSO已经有一段时间了,但我的gcc使用的任何库都没有。