【C++】014、左值与右值的区别

📅 2026/7/8 2:32:37
【C++】014、左值与右值的区别
一、左值右值左值左值是有内存地址的持久对象可以取他的地址值右值右值是临时的即将销毁的对象不能取他的地址但可以窃取他的资源。右值的存储位置通常在栈或者寄存器内。右值引用T右值引用是为了把右值这种临时资源拿来继续使用二、左值与右值的鉴别方法在C中能对表达式使用取地址运算符的就是左值不能取地址的就是右值int a 10; // a 是左值a 合法 int* p a; // ✅ OK // int* p2 10; // ❌ 编译错误不能对字面量取地址所以 10 是右值三、对比对比维度左值右值别名有身份的无身份的临时取地址操作可以不可以生命周期长有自己的作用域短面临销毁例子变量(a),i*ptr字面量10iMyClass()能否放在左边通常可以不可以除非使用move右值引用T不可以除非使用move可以四、移动赋值操作std::move1、窃取资源std::move 本质上只是一个强制类型转换static_cast不移动任何东西只是将左值变成右值。真正的移动发生在移动构造函数和移动赋值运算赋里编译器看到右值从而窃取资源而非深拷贝代码#include iostream #include vector #include utility // for std::move class BigData { private: std::vectorint data; // 假设很大10000个元素 public: // 1. 构造函数建立资源 explicit BigData(size_t size) : data(size, 1) { std::cout Constructed (allocated memory)\n; } // 2. 拷贝构造函数深拷贝开销大 BigData(const BigData other) : data(other.data) { std::cout Copied (expensive deep copy)!\n; } // 3. 移动构造函数轻量级指针交换C11核心 BigData(BigData other) noexcept : data(std::move(other.data)) { // 精髓直接窃取 other 的内部指针other.data 变为空 std::cout Moved (cheap pointer swap)!\n; } }; BigData createBigData() { BigData temp(10000); // 创建临时对象左值 return temp; // 返回时触发移动语义C17强制拷贝省略前优先选移动 } int main() { BigData obj1(10000); // 构造 BigData obj2 obj1; // 拷贝深复制慢 - 输出 Copied! BigData obj3 std::move(obj1); // 移动偷数据快 - 输出 Moved! // 注意此时 obj1 处于“有效但未指定”的状态通常是空不要再使用 obj1 }2、右值引用T专门用来捕获右值从而在不拷贝的情况下转移资源右值引用智能绑定右值如果想把左值当右值用必须通过move显示转换int a 5; int lr a; // OK // int lr2 10; // ❌ 错误 const int clr 10; // ✅ OK临时对象生命周期被延长到引用生命周期 int rr 10; // ✅ OK // int rr2 a; // ❌ 错误不能直接绑左值 int rr3 std::move(a); // ✅ OK强制转换此时a的资源可以被偷3、总结左值是有户口本的居民 右值是有暂住证的旅客 move是让居民办理临时注销把资源合法转移给新用户。