C++11 右值引用与移动语义详解
背景与历史发展
C++11 是 C++ 标准自 C++98 以来最重要的更新之一。在 2011 年 8 月正式采纳前,它曾被称为 C++0x。这次更新标准化了许多实践,引入了大量新特性,显著提升了 C++ 的抽象能力和性能表现。
值得注意的是,语言标准的普及通常有 5~10 年的缓冲期。目前大多数公司仍在使用 C++11 或 C++14,C++17 也在逐步推广,而 C++23 等新特性由于库支持尚不完善,大规模应用还需时间。
编译器支持情况
不同编译器对标准的支持程度不同。例如 VS (MSVC) 和 Clang 对 C++ 特性的支持进度不一。在实际开发中,建议查阅编译器文档确认具体特性的可用性。
列表初始化:{}
C++11 引入了统一的初始化方式——列表初始化(List Initialization),即使用 {}。
C++98 与 C++11 的区别
在 C++98 中,数组和结构体通常用 0 进行初始化。C++11 之后,一切对象皆可尝试用 {} 初始化。对于内置类型和自定义类型,这本质上是一种类型转换,中间可能产生临时对象,但编译器通常会优化为直接构造。
int i = {1}; // 合法
int j{2}; // 合法,省略了=号
Date d{2025, 11, 15}; // 自定义类型也支持
std::initializer_list
为了支持容器初始化任意数量的值,C++11 提供了 std::initializer_list。其底层实现是一个指向数组的指针结构,包含开始和结束指针。
auto il = {10, 20, 30}; // 类型为 std::initializer_list<int>
vector<int> v = {1, 2, 3}; // 容器构造函数支持 initializer_list
这使得 push_back 或构造函数可以接受不定数量的参数进行初始化。
左值与右值
理解右值引用的前提是区分左值和右值。
- 左值 (Lvalue):表示数据的表达式,通常具有持久状态,存储在内存中,可以取地址。例如变量名、解引用后的指针。它可以出现在赋值符号左边。
- 右值 (Rvalue):通常是字面常量或表达式求值产生的临时对象,不能取地址,一般只能出现在赋值符号右边。
int a = 10;
int& r1 = a; // 左值引用绑定左值
& r3 = a;


