找回密码
 立即注册
首页 业界区 业界 C++ 左值、右值、左值引用、右值引用

C++ 左值、右值、左值引用、右值引用

连热 2025-10-1 18:55:33
1、左值与右值

左值和右值是表达式的属性,核心区别在于:能否取地址、是否有持久的存储
1.1 左值:有名字、能取地址、可被修改(通常)

左值是 “可以放在赋值号左边” 的表达式(但并非绝对,如 const 左值不能被修改),它有明确的内存地址,生命周期较长(如变量)。
  1. int a = 10; // a 是左值(有名字、能取地址)
  2. int* p = &a; // 合法:左值可以取地址
  3. const int b = 20; // b 是 const 左值(有名字、能取地址,但不能修改)
  4. // b = 30; // 错误:const 左值不可修改
  5. int arr[5];
  6. arr[0] = 1; // arr[0] 是左值(数组元素有地址)
复制代码
1.2 右值:无名字、不能取地址、临时存在

右值是 “只能放在赋值号右边” 的表达式,通常是临时结果(如字面量、表达式计算结果),没有持久的内存地址,生命周期短暂(表达式结束后销毁)。
  1. int a = 10;
  2. int b = 20;
  3. // 以下都是右值
  4. 100; // 字面量(无名字,不能取地址)
  5. a + b; // 表达式结果(临时值,无名字)
  6. func(); // 函数返回值(非引用类型时,是临时值)
复制代码
关键特征

  • 右值不能被取地址:&(a + b) 会编译报错(无法对临时值取地址)。
  • 右值是 “消耗品”:使用后就会销毁(除非被保存到左值中)。
右值的细分
C++11 后,右值又分为两种,但日常使用中无需严格区分,知道它们都是右值即可:

  • 纯右值(Prvalue):字面量(如 10)、表达式结果(如 a + b)、非引用返回的函数结果。
  • 将亡值(Xvalue):通过 std::move 转换后的左值(本质是 “即将被销毁的左值”,可被移动)。
2、左值引用:绑定左值的 “别名”

左值引用是最常用的引用类型,用 & 表示,只能绑定左值,本质是给左值起一个 “别名”,操作引用等价于操作原对象。
2.1 基本用法
  1. int a = 10;
  2. int& ref_a = a; // 正确:左值引用绑定左值(ref_a 是 a 的别名)
  3. ref_a = 20; // 等价于 a = 20,a 现在是 20
复制代码
2.2 左值引用的限制


  • 不能绑定右值
    1. // int& ref = 10; // 错误:左值引用不能绑定右值(10 是右值)
    复制代码
  • const 左值引用是特例:可以绑定右值(临时延长右值的生命周期):
    1. const int& ref = 10; // 正确:const 左值引用可绑定右值
    2. // 原理:编译器会生成临时变量存储 10,ref 绑定这个临时变量(临时变量生命周期被延长至 ref 相同)
    复制代码
2.3 左值引用的用途


  • 避免函数传参时的拷贝(如传递大对象 vector):
    1. void func(const vector<int>& v) { ... } // 传引用,无拷贝
    复制代码
  • 允许函数修改外部变量(非 const 引用):
    1. void increment(int& x) { x++; }
    2. int a = 5;
    3. increment(a); // a 变为 6
    复制代码
3、右值引用:绑定右值的 “专属引用”

右值引用是 C++11 新增的引用类型,用 && 表示,专门绑定右值,目的是 “利用右值的临时特性” 实现移动语义(避免不必要的拷贝)。
3.1 基本用法
  1. int&& ref1 = 10; // 正确:右值引用绑定纯右值(10 是右值)
  2. int a = 10, b = 20;
  3. int&& ref2 = a + b; // 正确:右值引用绑定表达式结果(右值)
复制代码
3.2 右值引用的限制


  • 不能直接绑定左值:
    1. int a = 10;
    2. // int&& ref = a; // 错误:右值引用不能直接绑定左值
    复制代码
  • 但可以通过 std::move 将左值 “强制转换” 为右值引用(本质是告诉编译器:“这个左值可以被当作右值处理,资源可以被转移”)
    1. int a = 10;
    2. int&& ref = std::move(a); // 正确:std::move 将 a 转为右值引用
    复制代码
    注意:std::move 不会移动任何数据,只是 “标记” 左值为 “可被移动” 的右值,本身是编译期操作,无运行时开销。
3.3 右值引用的核心用途:移动语义

右值引用的最大价值是实现移动语义—— 对于临时对象(右值),不再进行昂贵的拷贝,而是直接 “窃取” 其资源(如内存),大幅提升性能。
移动构造函数
[code]class MyString {private:    char* data; // 存储字符串的动态内存public:    // 普通构造函数    MyString(const char* str) {        size_t len = strlen(str);        data = new char[len + 1];        strcpy(data, str);        cout
您需要登录后才可以回帖 登录 | 立即注册