作为右值 (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
}
我的问题是:
主要是 myVector
被函数 myFunction()
销毁,因为它被认为是右值,或者编译器是否知道它也是左值并因此执行发送到 myFunction
之前的副本?如果我在调用 myFunction()
后尝试使用向量会发生什么情况?
在函数 myFunction()
中,向量 givenVector
在受到 otherVector
影响时是否被破坏?如果是这样,当我尝试打印它时会发生什么?如果不是,在此函数中使用右值有用吗?
如果函数通过右值引用获取参数,这并不意味着它将被破坏性地使用,只是它可以.
破坏性使用意味着传递的对象此后处于某种未指定但有效的状态,仅适合重新初始化、移动、复制或销毁。
在函数中,参数有一个名字,因此是一个左值。
要标记你想利用许可证无情掠夺它的地方,你必须在传递它时将它转换为右值引用,例如 std::move
或 std::forward
,后者主要用于模板。
代码无法编译,因为您尝试将 lvalue 绑定到 rvalue 引用。您需要故意将其转换为 rvalue:
myFunction(std::move(givenVector));
简单地这样做不会 "destroy" 对象;它会发生什么取决于函数的作用。通常,采用 rvalue 引用的函数这样做是为了从参数中移出,在这种情况下,它们可能会使其处于某种有效但 "empty" 状态,但不会破坏它。
您的代码将矢量移动到本地 otherVector
,将其留空。然后你尝试打印一个空向量的第一个元素,给出未定义的行为。
不执行复制。 myVector
会发生什么取决于 myFunction
对它做了什么。您应该将已移出的对象视为相同或为空。您可以分配新值并继续使用或销毁它。
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。
myVector 未被函数 myFunction() 销毁。未指定 class 在一般情况下使用被盗资源会发生什么。
givenVector 在影响到 otherVector 时不会被破坏。未指定 class 在一般情况下使用被盗资源会发生什么。
我整天都在想这个问题,但找不到具体案例的答案。
主线:
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
}
我的问题是:
主要是
myVector
被函数myFunction()
销毁,因为它被认为是右值,或者编译器是否知道它也是左值并因此执行发送到myFunction
之前的副本?如果我在调用myFunction()
后尝试使用向量会发生什么情况?在函数
myFunction()
中,向量givenVector
在受到otherVector
影响时是否被破坏?如果是这样,当我尝试打印它时会发生什么?如果不是,在此函数中使用右值有用吗?
如果函数通过右值引用获取参数,这并不意味着它将被破坏性地使用,只是它可以.
破坏性使用意味着传递的对象此后处于某种未指定但有效的状态,仅适合重新初始化、移动、复制或销毁。
在函数中,参数有一个名字,因此是一个左值。
要标记你想利用许可证无情掠夺它的地方,你必须在传递它时将它转换为右值引用,例如 std::move
或 std::forward
,后者主要用于模板。
代码无法编译,因为您尝试将 lvalue 绑定到 rvalue 引用。您需要故意将其转换为 rvalue:
myFunction(std::move(givenVector));
简单地这样做不会 "destroy" 对象;它会发生什么取决于函数的作用。通常,采用 rvalue 引用的函数这样做是为了从参数中移出,在这种情况下,它们可能会使其处于某种有效但 "empty" 状态,但不会破坏它。
您的代码将矢量移动到本地 otherVector
,将其留空。然后你尝试打印一个空向量的第一个元素,给出未定义的行为。
不执行复制。
myVector
会发生什么取决于myFunction
对它做了什么。您应该将已移出的对象视为相同或为空。您可以分配新值并继续使用或销毁它。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。
myVector 未被函数 myFunction() 销毁。未指定 class 在一般情况下使用被盗资源会发生什么。
givenVector 在影响到 otherVector 时不会被破坏。未指定 class 在一般情况下使用被盗资源会发生什么。