std :: vector :: emplace_back和std :: move

Hum*_*awi 20 c++ vector move-semantics c++11

使用std::vector::emplace_backstd::move一起有什么好处?或者它只是多余的,因为std::vector::emplace_back会做一个inplace-construction?

案例澄清:

std::vector<std::string> bar;
Run Code Online (Sandbox Code Playgroud)

第一:

bar.emplace_back(std::move(std::string("some_string")));
Run Code Online (Sandbox Code Playgroud)

第二:

std::string str("some_string");
bar.emplace_back(std::move(str));
Run Code Online (Sandbox Code Playgroud)

第三:

bar.emplace_back(std::move("some_string"));
Run Code Online (Sandbox Code Playgroud)

Tar*_*ama 22

在第二个版本中,有一个优点.调用emplace_back将调用std::stringwhen std::move的使用时的移动构造函数,这可以保存在副本上(只要该字符串不存储在SSO缓冲区中).请注意,这与push_back本例中的基本相同.

std::move 在第一个版本中是不必要的,因为字符串已经是prvalue.

std::move 在第三个版本是无关紧要的,因为字符串文字无法移动.

最简单,最有效的方法是:

bar.emplace_back("some_string");
Run Code Online (Sandbox Code Playgroud)

这需要没有不必要的std::string构造,因为文字完美地转发给构造函数.


Dav*_*aim 6

emplace_back 打电话给某事

new (data+size) T(std::forward<Args>(args)...);
Run Code Online (Sandbox Code Playgroud)

如果args是basic - 非rvalue-referenced std::string,表达式将编译为

new (data+size) std::string(str); //str is lvalue - calls std::string::string(const string& rhs)
Run Code Online (Sandbox Code Playgroud)

意味着复制构造函数将发生.但是,如果你使用std::moveon str,代码将编译为

new (data+size) std::string(str); //str is r-value reference, calls std::string::string(string&& rhs)
Run Code Online (Sandbox Code Playgroud)

所以移动语义发生了.这是一个巨大的性能提升.
注意,这str是左值,它有一个名称,所以为了从它创建r值引用,你必须使用std::move.

在示例中

vec.emplace_back("some literal"); 
Run Code Online (Sandbox Code Playgroud)

代码将编译为

new (data+size) std::string("literal"); //calls std::string::string(const char*);
Run Code Online (Sandbox Code Playgroud)

所以没有临时工.

第三个例子是胡说八道.你不能移动文字.


Sta*_*tas 5

整个想法emplace_back是摆脱复制和移动操作。您只需要传递std::stringinto 的输入参数emplace_backstd::string将在emplace_back方法内部构造一个对象。

bar.emplace_back("some_string");
Run Code Online (Sandbox Code Playgroud)

如果您已经有一个字符串,那么使用std::move. std::stringemplace_back通过从 移动数据在内部构造一个对象str

std::string str("some_string");
bar.emplace_back(std::move(str));
Run Code Online (Sandbox Code Playgroud)