在 C++11 中,值参数(和其他值)在返回时享受隐式 move :
A func(A a) {
return a; // uses A::A(A&&) if it exists
}
至少在MSVC 2010中,右值引用参数需要std::move
:
A func(A && a) {
return a; // uses A::A(A const&) even if A::A(A&&) exists
}
我想在函数内部,右值引用和值的行为相似,唯一的区别是在值的情况下,函数本身负责销毁,而对于右值引用,责任在外部。
在标准中区别对待它们的动机是什么?
最佳答案
标准化委员会付出了巨大的努力来创建措辞,以便只在两种情况下才会采取行动:
- 在明显安全的情况下这样做。
- 当用户明确询问时(通过
std::move
或类似的类型转换)。
值参数无疑会在函数结束时被销毁。因此,通过 move 将其返回显然是安全的;返回后其他代码无法触及它(除非您故意尝试破坏事物,否则您可能会触发未定义的行为)。因此,它可以从返回中移出。
一个 &&
变量可能指的是临时的。但它可能指的是一个左值(一个命名变量)。因此,离开它显然是不安全的;原始变量可能潜伏在周围。而且由于您没有明确要求从它 move (即:您没有在此函数中调用 std::move
),因此不会发生 move 。
唯一的一次&&
当您 return 时,变量将被隐式 move (即:没有 std::move
)。 std::move<T>
返回 T&&
.该返回值调用 move 构造函数是合法的,因为它是一个返回值。
现在打电话很困难A func(A &&a)
有一个左值没有调用std::move
(或等效的类型转换)。所以从技术上讲,它 应该 适合 &&
的参数要隐式 move 的类型。但标准委员会希望对 &&
采取明确的行动。类型,只是为了确保 move 不会在此函数的范围内隐式发生。也就是说,它不能使用关于 &&
位置的函数外知识。来自。
一般情况下,您应该只使用 &&
的参数。在两种情况下:要么您正在编写 move 构造函数(或 move 赋值运算符,但即使这也可以通过值完成),或者您正在编写转发函数。可能还有其他几种情况,但你不应该采取&&
除非你有特别的想法。如果 A
是可 move 的类型,那么就按值取吧。
关于c++ - 为什么 C++11 对值参数有隐式 move ,但对右值参数没有?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9779079/