c++中的左值右值,以及左值引用和右值引用
理解左值lvalue和右值rvalue是掌握C资源管理的基础。下面这个表格能帮你快速抓住核心概念。 理解左值引用与右值引用引用Reference是为已存在对象起的一个别名。根据引用的对象不同分为左值引用和右值引用。左值引用 (T)传统C中的引用只能绑定到左值。inta10;intlrefa;// 正确左值引用绑定到左值a// int bad_ref 10; // 错误非const左值引用不能绑定到右值但有一个重要的例外const左值引用 (const T)。它可以绑定到左值也可以绑定到右值常被用作函数参数以避免不必要的拷贝。constintconst_lref10;// 正确const左值引用可以绑定到右值voidprint(conststd::stringstr);// 可接受左值或右值如 print(Hello)右值引用 (T)C11引入只能绑定到右值。其主要使命是实现移动语义Move Semantics避免不必要的深拷贝提升性能。intrref10;// 正确右值引用绑定到右值10intb20;// int bad_rref b; // 错误右值引用不能直接绑定到左值b可以使用 std::move将一个左值显式转换为右值引用从而允许移动语义作用于它。std::string str1Hello;std::string str2std::move(str1);// 调用移动构造函数str1的资源被“移动”到str2// 此后str1处于有效但未定义的状态不应再使用其值 核心价值移动语义与完美转发右值引用的价值主要体现在两个方面移动语义 (Move Semantics)通过定义移动构造函数和移动赋值运算符将资源如动态内存从右值通常是临时对象“窃取”过来而非进行昂贵的深拷贝classMyString{char*data;public:// 移动构造函数MyString(MyStringother)noexcept:data(other.data){other.datanullptr;// 使原对象处于有效状态}// 移动赋值运算符MyStringoperator(MyStringother)noexcept{if(this!other){delete[]data;dataother.data;other.datanullptr;}return*this;}};2.完美转发 (Perfect Forwarding)在模板编程中T可能是万能引用Universal Reference。结合 std::forward可以保持参数原有的左值/右值属性将其完美地转发给其他函数。templatetypenameTvoidwrapper(Targ){target(std::forwardT(arg));// 完美转发}⚠️ 关键注意事项右值引用变量本身是左值。一个具名的右值引用如函数参数有标识符可取地址因此是左值。这是为了确保安全防止资源被意外多次转移。谨慎使用 std::move。对一个对象使用 std::move后其资源已被移走不应再使用其值。编译器优化。现代编译器会进行返回值优化RVO/NRVO有时能避免拷贝和移动不要为了移动而移动。 总结理解左值/右值及其引用的关键在于身份和资源的所有权。左值引用 (T) 主要用作只读参数或修改持久对象右值引用 (T) 的核心是移动语义通过资源转移极大提升处理大型对象的效率。std::move用于将左值转为右值std::forward用于模板中的完美转发。