C++ 将字符串从stringstream移动到字符串向量中
我有一个C++ 将字符串从stringstream移动到字符串向量中,c++,string,c++11,stl,stringstream,C++,String,C++11,Stl,Stringstream,我有一个std::stringstream ss和一个std::vector列表 我想向后推(或向后放置)ss到列表 如何以最佳方式避免额外复制ss的支持字符串 我的意图是立即运行ss.clear(),因为我将重新填充它(稍后附加到列表中) 可能的选择: list.emplace\u back(std::move(ss.str()) list.emplace\u back(ss.str()) list.push_-back(std::move(ss.str()) 列表。向后推(ss.str())
std::stringstream ss
和一个std::vector列表
我想向后推
(或向后放置
)ss
到列表
如何以最佳方式避免额外复制ss
的支持字符串
我的意图是立即运行ss.clear()
,因为我将重新填充它(稍后附加到列表中)
可能的选择:
list.emplace\u back(std::move(ss.str())
list.emplace\u back(ss.str())
list.push_-back(std::move(ss.str())
列表。向后推(ss.str())
ss
中会保留什么?(在任何情况下我都会扔掉它)
导致我不确定该做什么的原因是。尽管我没有将stringstreams移动到另一个容器中,但我现在特别担心的是能否将构建为stringstream的字符串(可能是巨大的)移动到字符串容器的后面。显然如果str()
的实现方式会导致一些复制或转换,这是不可避免的,但我希望生成的代码能够以恒定的时间将其填充到向量的后面
我研究了str()
的实现:
模板
基本字符串
基本字符串buf::str()常量
{
如果(\uuuuu模式\uiOS\uU基::输出)
{
如果(uuhm_uupptr())
__hm_=此->pptr();
返回字符串类型(this->pbase(),\uuuuhm,\uuuuu str.get\u分配器());
}
else if(uuuu mode_uuu&ios_ubase::in)
返回字符串类型(this->eback(),this->egptr(),uuu str_u.get_分配器());
返回字符串类型(uu str_u.get_分配器());
}
复制函数返回值在默认情况下已经是std::moved.ie
std::string herp() { return string("lalalalala"); }
std::string derp (herp ());
将使用derp的std::string移动构造函数
正如您在下面的代码中所看到的,将使用移动分配操作符。
在内部,字符串自身的操作符=(&&&)
将与字符串ss.str()交换。将返回
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
class Herp {
string internal;
public:
const Herp& operator=(const string& s)
{
cout<<"Standard initialize operator\n";
internal = s;
return *this;
}
const Herp& operator=(string&& s)
{
cout<<"Move initialize operator\n";
internal = s;
return *this;
}
};
int main()
{
Herp a;
stringstream ss;
ss<<string("abcdef");
a = ss.str();
return 0;
}
#包括
#包括
#包括
使用名称空间std;
班主任{
字符串内部;
公众:
常量Herp和运算符=(常量字符串和运算符)
{
cout对于这种情况,想法如下:
1) ss返回一个字符串,该字符串是stringstream文本的内部表示形式的副本,字符串有一个内部缓冲区和一个指针(这就是为什么move对字符串有意义,尽管也有)
2) 由于返回的字符串在传递到emplace back时是一个临时值,它将在vector中移动一个字符串对象,因此不会有内部缓冲区的副本(只有指针和一些整数在临时字符串和新字符串之间交换,这是非常便宜的)。这里几乎同样适用于push_back
所以
list.emplace_back(std::move(ss.str())
list.emplace_back(ss.str())
list.push_back(std::move(ss.str())
list.push_back(ss.str())
所有案例都必须做几乎相同的事情(这意味着它们不会复制临时字符串缓冲区)。一如既往地分析并看看有什么更好,但我怀疑在这种情况下是否有明显的区别。正如前面所说的,所有四个选项最终都做相同的事情,并且都是最佳的-它们移动str()返回的临时字符串
(这是一个右值,因此和&
推回的重载将应用)到向量的后面。emplace\u back
在您有一组参数要传递给value\u type
的构造函数时非常有用。请考虑:
std::vector<std::pair<std::string, std::string>> vec;
vec.push_back(std::make_pair("Hey", "You")); // a temporary pair is created here
vec.emplace_back("Hey", "You"); // arguments are forwarded to the constructor of
// pair which is constructed in place
你不需要调用std::move()
,因为ss.str()
已经返回了一个右值。如果我没有弄错的话,我需要从中提取一个x值。emplace\u back
也许可以强制这样做?或者什么?我的理解是模糊的。(我认为这也可能是错误的。Emplace_back将使用args在适当的位置构建某些内容以传递给类型的ctor…这实际上是一个复制操作。不需要。)ss.str()是一个副本右值,由std::vector的移动副本移动operator@Julius什么是拷贝值?rValk?如果其他人读到这个,同样会被EffisteBead弄混淆,这里有一个很好的讨论:谢谢,这对我来说仍然是个黑魔法,我最近一直在写很多C++。还有很多要学习。现在,我是~ 80%肯定A。关于这一点,但请验证您是否愿意:我应该使用emplace\u back
,然后我可以跳过std::move
,因为它基本上只是转发ss.str()
移动到std::string的移动向量。是吗?使用push_back
是否也会移动它?如果我想将它推到向量,但我仍然想要访问它(即,我实际上想要一个副本…),这与push back一起工作。emplace back被特别称为不使用move操作符,如()哈?那么这是向后的吗?emplace\u back
复制,push\u back
移动?我他妈的该如何从阅读文档中做出这个推断?对于push\u back
,它说只有当T满足MoveInsertable的要求时才使用第二个ctor,我不知道ss.str()的值
符合这个标准。因此这个问题。对于安置回
,好的,回到我关于安置回的原始结论,即我不能使用它(因为我想移动,而不是复制或构造)你能看看我在@Julius答案的评论上贴的colirus吗?它们表明发生了一个拷贝。也许有一个不可避免的拷贝总是作为str()
的一部分发生?也许这是SSO的结果。每当一个新的临时字符串出现时,ss.str()就会返回。在示例代码中,你调用了ss.st
std::vector<std::pair<std::string, std::string>> vec;
vec.push_back(std::make_pair("Hey", "You")); // a temporary pair is created here
vec.emplace_back("Hey", "You"); // arguments are forwarded to the constructor of
// pair which is constructed in place
list.emplace_back(std::move(ss).str());