NRVO 和 Move Semantics 可以在 C++ 中一起使用吗?

问题描述 投票:0回答:2

我正在从《C++ Move Semantics》一书中阅读有关 C++ 中的移动语义的内容。本书假设

NRVO
用于
createAndInsert()
函数的 return 语句中。但是,它还指出,当在
v = createAndInsert();
中执行
main()
时,将应用移动语义。

我的问题是:如果已经应用了 NRVO,是否应该直接在

coll
的空间中构造
v
,从而使
main()
中不需要任何移动操作?这可能是为了书中的学习目的,还是暗示如果不应用
NRVO
会发生什么,尽管它已经声明了?我试图了解我是否遗漏了有关 NRVO 和移动语义在这种情况下如何交互的信息。

感谢您的见解!

#include <string>
#include <vector>

std::vector<std::string> createAndInsert()
{
    std::vector<std::string> coll;  // create vector of strings
    coll.reserve(3);                // reserve memory for 3 elements
    std::string s = "data";         // create string object

    coll.push_back(s);              // insert string object
    coll.push_back(s+s);            // insert temporary string
    coll.push_back(std::move(s));   // insert string (we no longer need the value of s)

    return coll;                    // return vector of strings
}

int main()
{
    std::vector<std::string> v;     // create empty vector of strings
    //...
    v = createAndInsert();          // assign returned vector of strings
    //...
}
c++ move-semantics nrvo
2个回答
3
投票

如果您要执行

std::vector<std::string> v = createAndInsert();
,首先会从
coll
移动到返回的临时文件(NRVO 可能会或可能不会删除它),然后从该临时文件再次移动到
v
(这总是被删除,因为C++17).

但是在执行

std::vector<std::string> v; v = createAndInsert();
时,第二个动作永远无法被省略,因为对象已经构造好了。


1
投票

v = createAndInsert();
v.operator=(createAndInsert());
完全相同。
createAndInsert()
的返回值绑定到移动赋值运算符的
std::vector<std::string>&&
参数,因此必须将其移出。

operator=
与任何其他功能没有什么不同。如果有一个名为
f
的成员函数想要从其参数进行赋值,则
v.f(createAndInsert())
必须创建另一个对象来传递给该函数。只有这样才能摆脱争论。

要消除移动和其他对象,您必须直接从中初始化:

int main()
{
  // std::vector<std::string> v;
  //...
  // The result would be constructed directly into v
  std::vector<std::string> v = createAndInsert();
  //...
}
int main()
{
  std::vector<std::string> v;     // create empty vector of strings
  //...
  std::destroy_at(&v);
  ::new (&v) auto(createAndInsert());  // construct returned vector of strings into v
  // Though this method has a lot of problems if `createAndInsert` throws
  //...
}
© www.soinside.com 2019 - 2024. All rights reserved.