[英]std::vector::emplace_back and std::move
Is there any advantage of using std::vector::emplace_back
and std::move
together? 使用
std::vector::emplace_back
和std::move
有什么好处吗? or it is just redundant since std::vector::emplace_back
will do an inplace-construction? 或者它只是多余的,因为
std::vector::emplace_back
将进行std::vector::emplace_back
-construction?
Cases for clarification: 案例澄清:
std::vector<std::string> bar;
First: 第一:
bar.emplace_back(std::move(std::string("some_string")));
Second: 第二:
std::string str("some_string");
bar.emplace_back(std::move(str));
Third: 第三:
bar.emplace_back(std::move("some_string"));
In the second version, there is an advantage. 在第二个版本中,有一个优点。 Calling
emplace_back
will call the move constructor of std::string
when std::move
is used, which could save on a copy (so long as that string isn't stored in a SSO buffer). 当使用
std::move
时,调用emplace_back
将调用std::string
的move构造函数,这可以保存在副本上(只要该字符串不存储在SSO缓冲区中)。 Note that this is essentially the same as push_back
in this case. 请注意,在这种情况下,这与
push_back
基本相同。
std::move
in the first version is unnecessary, as the string is already a prvalue. 第一个版本中的
std::move
是不必要的,因为字符串已经是prvalue。
std::move
in the third version is irrelevant, as a string literal cannot be moved from. std::move
在第三个版本中是无关紧要的,因为无法移动字符串文字。
The simplest and most efficient method is this: 最简单,最有效的方法是:
bar.emplace_back("some_string");
That requires no unnecessary std::string
constructions as the literal is perfect-forwarded to the constructor. 这需要没有不必要的
std::string
结构,因为文字完美地转发给构造函数。
emplace_back
calls to somehthing like emplace_back
调用了类似的东西
new (data+size) T(std::forward<Args>(args)...);
if args
are basic - non - rvalue-referenced std::string
, the expression will compile to 如果
args
是基本的 - 非rvalue引用的std::string
,则表达式将编译为
new (data+size) std::string(str); //str is lvalue - calls std::string::string(const string& rhs)
meaning the copy constructor will take place. 意味着复制构造函数将发生。 but, if you use
std::move
on str
, the code will compile to 但是,如果你在
str
上使用std::move
,代码将编译为
new (data+size) std::string(str); //str is r-value reference, calls std::string::string(string&& rhs)
so move semantics takes place. 所以移动语义发生了。 this is a huge performance gain.
这是一个巨大的性能提升。
do note, that str
is lvalue, it has a name, so in order to create r-value-reference from it, you must use std::move
. 注意,
str
是左值,它有一个名称,所以为了从它创建r值引用,你必须使用std::move
。
in the example 在示例中
vec.emplace_back("some literal");
the code will compile to 代码将编译为
new (data+size) std::string("literal"); //calls std::string::string(const char*);
so no temporaries. 所以没有临时工。
the third example is nonsense. 第三个例子是胡说八道。 you cannot move literals.
你不能移动文字。
The whole idea of emplace_back
is to get rid of copying and moving operations. emplace_back
的整个想法是摆脱复制和移动操作。 You just need to pass input parameters of std::string
into emplace_back
. 您只需要将
std::string
输入参数传递给emplace_back
。 A std::string
object will be constructed inside emplace_back
method. 将在
emplace_back
方法中构造一个std::string
对象。
bar.emplace_back("some_string");
If you already have a string, it makes sense to use std::move
. 如果你已经有了一个字符串,那么使用
std::move
是有意义的。 A std::string
object will be constructed inside emplace_back
by moving data from str
. 通过从
str
移动数据,将在emplace_back
内构造一个std::string
对象。
std::string str("some_string");
bar.emplace_back(std::move(str));
There is a point of doing so in the second case. 在第二种情况下,有一点是这样做的。 Consider this code:
考虑以下代码:
int main()
{
std::vector<std::string> bar;
std::string str("some_string");
bar.emplace_back(std::move(str)); str.clear();
// bar.emplace_back(str);
std::cout << str << std::endl;
}
If you change the comment to the line above, you can see that you will end up with two copies of "some_string" (one in bar
and one in str
). 如果您将注释更改为上面的行,您可以看到最终会有两个“some_string”副本(一个在
bar
,一个在str
)。 So it does change something. 所以它确实改变了一些东西
Otherwise, the first one is moving a temporary, and the third is moving a constant string literal. 否则,第一个是移动临时,第三个是移动一个常量字符串文字。 It does nothing.
它什么都不做。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.