Arn*_*rno 21 c++ rvalue-reference move-semantics c++11 c++20
在C++ 11中,值参数(和其他值)在返回时享受隐式移动:
A func(A a) {
return a; // uses A::A(A&&) if it exists
}
Run Code Online (Sandbox Code Playgroud)
至少在MSVC 2010中,右值参考参数需要std::move:
A func(A && a) {
return a; // uses A::A(A const&) even if A::A(A&&) exists
}
Run Code Online (Sandbox Code Playgroud)
我认为内部函数,右值引用和值的行为类似,唯一的区别是在值的情况下,函数本身负责销毁,而对于右值引用,责任在外面.
在标准中对待它们的动机是什么?
Nic*_*las 25
标准化委员会在创建措辞方面付出了巨大的努力,因此只有在两种情况下才会发生变化:
std::move或类似演员)时.毫无疑问,值参数将在函数末尾被销毁.因此,通过移动返回它显然是安全的; 返回后它不能被其他代码触及(除非你故意试图破坏事物,在这种情况下你可能会触发未定义的行为).因此,它可以从返回中移动.
一个&&变量可能是指的是暂时的.但它可能指的是左值(一个命名变量).因此,离开它是不明显的安全; 原始变量可能潜伏着.而且由于你没有明确要求从中移动(即:你没有调用std::move此函数),所以不能进行任何移动.
&&变量将被隐式移动(即:没有std::move)的唯一时间是返回它.std::move<T>返回一个T&&.返回值调用move构造函数是合法的,因为它是返回值.
现在很难在不调用(或等效A func(A &&a)的强制转换)的情况下使用左值调用std::move.因此从技术上讲,对于隐式移动类型的参数应该没问题&&.但标准委员会希望对&&类型进行明确的移动,只是为了确保移动不会隐含地发生在此函数的范围内.也就是说,它不能使用关于&&来自何处的功能外知识.
一般来说,你应该只&&在两种情况下采用参数:要么你正在编写一个移动构造函数(或移动赋值运算符,甚至可以通过值来完成),或者你正在编写转发函数.可能还有其他几种情况,但&&除非你有一些特别的东西,否则你不应该采取类型.如果A是可移动类型,那么只需按值进行.
在您的第一种情况下,编译器知道它a正在消失并且没有任何东西能够附着在它上面:显然,这个对象可以从中移动,如果不是,它将被销毁。在第二种情况下,右值引用表示允许从对象移动,并且调用者不希望对象停留在周围。但是,是否利用此权限是函数的选择,并且可能存在函数有时想要从参数移动而有时不想移动的原因。如果编译器可以自由地离开这个对象,就没有办法阻止编译器这样做。但是,使用std::move(a)已经有一种方法可以指示希望从对象移动。
标准中的一般规则是编译器只会隐式移动已知会消失的对象。当一个右值引用进来时,编译器并不真正知道该对象即将离开:如果它被明确地std::move()编辑过,它实际上仍然存在。
| 归档时间: |
|
| 查看次数: |
3688 次 |
| 最近记录: |