Effective Modern C++: 右值引用
一:C语言中的右值概念
左值:既能出现在等号左边,又能出现在等号右边的变量(或表达式),可以寻址
右值:智能出现在等号右边的变量或表达式,无法寻址
例如:a = 10, a是左值,10就是右值
二:右值引用 rValue reference
C++11中用&&代表右值引用,左值引用只能引用左值,右值引用只能引用右值。
const T& 这个比较特殊,既能绑定左值,也能绑定右值
示例代码:
1 class A{ 2 public: 3 int a; 4 A(){} 5 }; 6 7 A getTemp() { 8 return A(); 9 } 10 11 int main(){ 12 A a; 13 A& refA = a; //lValue 14 A&& refA2 = getTemp(); //rValue 15 const A& cRefA = a; 16 const A& cRefA2 = getTemp(); 17 18 refA2 = std::move(refA); 19 return 0; 20 }
三:std::move
- move函数的参数T&&是一个指向模板类型参数的右值引用【规则2】,通过引用折叠,此参数可以和任何类型的实参匹配,因此move既可以传递一个左值,也可以传递一个右值;
在C++14中std::move模板方法的定义;
1 template<typename T> // C++14; still in 2 decltype(auto) move(T&& param) // namespace std 3 { 4 using ReturnType = remove_reference_t<T>&&; 5 return static_cast<ReturnType>(param); 6 } 7 8 摘录来自: “Effective Modern C++。” Apple Books.
四:std::forward
- std::forward实现了参数在传递过程中保持其值属性的功能,即若是左值,则传递之后仍然是左值,若是右值,则传递之后仍然是右值。
- std::move 和 std::forward的差别:
- std::move执行到右值的无条件转换。就其本身而言,它没有move任何东西。
- std::forward只有在它的参数绑定到一个右值上的时候,它才转换它的参数到一个右值。
- std::move和std::forward只不过就是执行类型转换的两个函数;std::move没有move任何东西,std::forward没有转发任何东西。在运行期,它们没有做任何事情。它们没有产生需要执行的代码,一byte都没有。
- std::forward<T>()不仅可以保持左值或者右值不变,同时还可以保持const、Lreference、Rreference、validate等属性不变;
- 示例:
1 class Widget{}; 2 3 void processWidget(const Widget& w){ 4 std::cout<< "Process lValue"<<std::endl; 5 } 6 7 void processWidget(Widget&& w){ 8 std::cout<<"Process rValue"<<std::endl; 9 } 10 11 template<typename T> 12 void logAndProcess(T&& param){ 13 processWidget(param); 14 } 15 16 int main(){ 17 Widget w; 18 logAndProcess(w); 19 logAndProcess(std::move(w)); 20 }
上述代码输出并不是所预期的lValue和rValue,需要std::forward()对传入参数进行完美转发。
1 class Widget{}; 2 3 void processWidget(const Widget& w){ 4 std::cout<< "Process lValue"<<std::endl; 5 } 6 7 void processWidget(Widget&& w){ 8 std::cout<<"Process rValue"<<std::endl; 9 } 10 11 template<typename T> 12 void logAndProcess(T&& param){ 13 processWidget(std::forward<T>(param)); 14 } 15 16 int main(){ 17 Widget w; 18 logAndProcess(w); 19 logAndProcess(std::move(w)); 20 }

浙公网安备 33010602011771号