C++ 左值(lvalue)、右值(rvalue)与右值引用(rvalue reference)
理解 C++ 中的左值、右值及其引用形式,是掌握现代 C++(尤其是 C++11 以后的移动语义/move和完美转发/perfect forwarding)必不可少的基础。
📌 什么是左值(lvalue)
左值指的是有名字、可寻址的对象,通常可以出现在赋值语句的左侧。
1
2
3
int x = 10;
x = 20; // x 是左值
int* p = &x; // 可以取地址
int x = 10;
x = 20; // x 是左值
int* p = &x; // 可以取地址
📌 什么是右值(rvalue)
右值是临时对象,不能被取地址,通常是表达式的结果或字面值常量。
1
2
3
int x = 10;
int y = x + 5; // x + 5 是右值
y = 100; // 100 是右值
int x = 10;
int y = x + 5; // x + 5 是右值
y = 100; // 100 是右值
右值不能出现在赋值语句左侧,且生命周期通常较短。
📌 右值引用(rvalue reference)
C++ 11 引入了右值引用(通过 && 语法),允许我们“捕获”右值。这为移动语义提供了基础。
1
2
3
4
5
6
7
8
void process(int& x); // 左值引用
void process(int&& x); // 右值引用
int main() {
int a = 42;
process(a); // 调用 int&
process(10); // 调用 int&&
}
void process(int& x); // 左值引用
void process(int&& x); // 右值引用
int main() {
int a = 42;
process(a); // 调用 int&
process(10); // 调用 int&&
}
右值引用通常与移动构造函数、移动赋值运算符、std::move 和完美转发/forwarding一起使用。
📊 左值 vs 右值 比较
特性
左值(lvalue)
右值(rvalue)
是否有名称
有
通常没有
是否可取地址
可以
不可以
是否可出现在赋值语句左侧
可以
不可以
生命周期
受作用域控制
通常是临时的
是否可绑定到 &&
否
是
🧪 std::move 与移动语义
1
2
std::string a = "hello";
std::string b = std::move(a); // a 被“移”给了 b
std::string a = "hello";
std::string b = std::move(a); // a 被“移”给了 b
std::move 并不移动对象,它只是把左值强制转换为右值,从而触发移动构造函数或移动赋值运算符。
💡 使用建议
使用左值引用(&):
当你需要访问和修改已有变量
不涉及资源转移
使用右值引用(&&):
希望接管临时对象的资源
编写移动构造函数或移动赋值
优化性能,避免深拷贝
总结
左值和右值是 C++ 表达式语义的核心。右值引用是现代 C++ 的重要特性,能显著提高资源管理和性能表现。理解它们的区别和用法,是成为高阶 C++ 程序员的基础。
C/C++编程
C++的左值/lvalue, 右值/rvalue和右值引用/rvalue references
C++中的assert和static_assert的区别
C++: auto_ptr智能指针被弃用
C++中的consteval是什么? 它与const和constexpr有何不同?
C++ 教程: 用std::move来移动所有权
C++中的 const和constexpr 比较
简易教程: C++的智能指针
C++ 编程练习题: 如何合并两个二叉树?
C++ 编程练习题 - 找出第三大的数
C++ 编程练习题 - 最多连续的 1
C++ 编程练习题 - 左子树叶节点之和 (深度优先+广度优先+递归)
C++ 编程练习题 - 最多水容器 (递归)
C++的异步编程: std::future, std::async 和 std::promise
C编程练习题: 翻转整数位
C++编程练习题: 找出字符串的所有大小小组合
C/C++ 中的内存管理器(堆与栈)
C++编程练习题: 对两单向链表求和
英文:C++ Lvalue, Rvalue and Rvalue References
GD Star Ratingloading... 本文一共 541 个汉字, 你数一下对不对.