连热 发表于 2025-10-1 18:55:33

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

1、左值与右值

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

左值是 “可以放在赋值号左边” 的表达式(但并非绝对,如 const 左值不能被修改),它有明确的内存地址,生命周期较长(如变量)。
int a = 10; // a 是左值(有名字、能取地址)
int* p = &a; // 合法:左值可以取地址

const int b = 20; // b 是 const 左值(有名字、能取地址,但不能修改)
// b = 30; // 错误:const 左值不可修改

int arr;
arr = 1; // arr 是左值(数组元素有地址)1.2 右值:无名字、不能取地址、临时存在

右值是 “只能放在赋值号右边” 的表达式,通常是临时结果(如字面量、表达式计算结果),没有持久的内存地址,生命周期短暂(表达式结束后销毁)。
int a = 10;
int b = 20;

// 以下都是右值
100; // 字面量(无名字,不能取地址)
a + b; // 表达式结果(临时值,无名字)
func(); // 函数返回值(非引用类型时,是临时值)关键特征:

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

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

左值引用是最常用的引用类型,用 & 表示,只能绑定左值,本质是给左值起一个 “别名”,操作引用等价于操作原对象。
2.1 基本用法

int a = 10;
int& ref_a = a; // 正确:左值引用绑定左值(ref_a 是 a 的别名)

ref_a = 20; // 等价于 a = 20,a 现在是 202.2 左值引用的限制


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


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

右值引用是 C++11 新增的引用类型,用 && 表示,专门绑定右值,目的是 “利用右值的临时特性” 实现移动语义(避免不必要的拷贝)。
3.1 基本用法

int&& ref1 = 10; // 正确:右值引用绑定纯右值(10 是右值)

int a = 10, b = 20;
int&& ref2 = a + b; // 正确:右值引用绑定表达式结果(右值)3.2 右值引用的限制


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

右值引用的最大价值是实现移动语义—— 对于临时对象(右值),不再进行昂贵的拷贝,而是直接 “窃取” 其资源(如内存),大幅提升性能。
移动构造函数
class MyString {private:    char* data; // 存储字符串的动态内存public:    // 普通构造函数    MyString(const char* str) {      size_t len = strlen(str);      data = new char;      strcpy(data, str);      cout
页: [1]
查看完整版本: C++ 左值、右值、左值引用、右值引用