作为右值 (c++) 在函数中传递的左值会发生什么?

what happens to lvalue passed in function as rvalue (c++)?

我整天都在想这个问题,但找不到具体案例的答案。

主线:

std::vector<MyObject*> myVector;
myVector.reserve(5);
myFunction(std::move(myVector));

我的函数:

void myFunction(std::vector<MyObject*> && givenVector){
    std::vector<MyObject*> otherVector = givenVector;
    std::cout << givenVector[0];
    // do some stuff
}

我的问题是:

  1. 主要是 myVector 被函数 myFunction() 销毁,因为它被认为是右值,或者编译器是否知道它也是左值并因此执行发送到 myFunction 之前的副本?如果我在调用 myFunction() 后尝试使用向量会发生什么情况?

  2. 在函数 myFunction() 中,向量 givenVector 在受到 otherVector 影响时是否被破坏?如果是这样,当我尝试打印它时会发生什么?如果不是,在此函数中使用右值有用吗?

如果函数通过右值引用获取参数,这并不意味着它将被破坏性地使用,只是它可以.

破坏性使用意味着传递的对象此后处于某种未指定但有效的状态,仅适合重新初始化、移动、复制或销毁。

在函数中,参数有一个名字,因此是一个左值。
要标记你想利用许可证无情掠夺它的地方,你必须在传递它时将它转换为右值引用,例如 std::movestd::forward ,后者主要用于模板。

代码无法编译,因为您尝试将 lvalue 绑定到 rvalue 引用。您需要故意将其转换为 rvalue:

myFunction(std::move(givenVector));

简单地这样做不会 "destroy" 对象;它会发生什么取决于函数的作用。通常,采用 rvalue 引用的函数这样做是为了从参数中移出,在这种情况下,它们可能会使其处于某种有效但 "empty" 状态,但不会破坏它。

您的代码将矢量移动到本地 otherVector,将其留空。然后你尝试打印一个空向量的第一个元素,给出未定义的行为。

  1. 不执行复制。 myVector 会发生什么取决于 myFunction 对它做了什么。您应该将已移出的对象视为相同或为空。您可以分配新值并继续使用或销毁它。

  2. myVector 没问题。它是一个左值,otherVector 复制了它。您很可能想写 otherVector = std::move(myVector);,在这种情况下 myVector 应该为空。如果您有旧的 STL 实现(不知道移动语义),则会执行复制并且 myVector 不会更改。如果这有意义,则由您决定。您将给定的 vector 移动到新的 vector,这可能很有用。打印一个空的 vector 不是很有用。

为了可编译,您应该在将向量传递给函数之前将 std::move 应用于向量(至少在不存在进一步重载的情况下):

myFunction(std::move(myVector));

然后,在函数内部,通过

std::vector<MyObject*> otherVector = std::move(givenVector);  

调用 std::vector 的移动构造函数,它基本上将所有内容移出向量(但是再次注意右侧的 std::move —— 否则你会得到一个复制)。这样,矢量就不是"destroyed"。即使在移动之后它仍然存在,但处于 未指定 状态。

也就是说可以调用那些对vector的状态没有特定条件的成员函数,比如析构函数,size()操作符等等。但是,pop_back() 或向量元素的取消引用可能会失败。

请参阅 here 以获取更详细的说明,您仍然可以对移出的对象执行哪些操作。

看起来像 duplicate

  1. myVector 未被函数 myFunction() 销毁。未指定 class 在一般情况下使用被盗资源会发生什么。

  2. givenVector 在影响到 otherVector 时不会被破坏。未指定 class 在一般情况下使用被盗资源会发生什么。