C++ 作为一门经典且持续演进的编程语言,其标准迭代始终围绕提升开发效率、优化性能和完善语言特性展开。1998 年发布的 C++98 奠定了语言基础,而 2011 年发布的 C++11 标准则堪称一次里程碑式的更新。它不仅修复了早期版本的诸多缺陷,更引入了大量革命性特性,从根本上改变了 C++ 的编程范式,为开发者提供了更简洁、高效且安全的编码工具。
本文将聚焦 C++11 标准的核心新增特性,从统一列表初始化的语法简化、auto/decltype/nullptr 的声明优化,到 STL 容器与接口的扩展,再到右值引用、移动语义、完美转发等深刻影响性能的底层机制,以及类功能的增强(如默认移动构造、final/override 关键字),系统梳理这些特性的设计逻辑与实际应用场景。
统一的列表初始化
C++11 扩大了用大括号括起的列表的使用范围,使其可用于所有的内置类型和用户自定义的类型。使用列表初始化时,可添加等号 (=),也可不添加。在 C++11 中,列表初始化也可以适用于 new 表达式中。
int y = {2};
int y{2};
struct Point {
Point(int x, int y) : _x(x), _y(y) {}
int _x;
int _y;
};
Point p1 = {1, 1};
Point p1{1, 1}; // 等价于 Point p1(1, 1)
上面两个例子其实也是调用了 Point 的构造函数,这是 C++11 支持多参数构造函数的隐式类型转换的表现。如果希望阻止这种隐式转换,可以在构造函数前加 explicit 关键字。
// 数组初始化示例
Point* ptr3 = new Point[2]{{0, 0}, {1, 1}};
const Point& r = {3, 3}; // const 不能去掉,因为创建了一个临时对象
initializer_list
这是一个特殊的类型。当 auto 用于初始化列表 {...} 时,编译器会优先推导出 std::initializer_list 类型。一般容器的构造函数和赋值=都支持这个类型进行初始化。
std::vector<int> v1 = {1, 2, 3, 4, 3}; // 调用 initializer_list 的 vector 构造函数
注意:上面的 {1, 2, 3, 4, 3} 转换成 initializer_list 类型时,其实是编译器会在常量区自动创建一个隐藏的常量数组,initializer_list 只是用指针引用这个数组,而不是自己存储数据。这个类型自己模拟实现不太行,库里面的这个类型编译器会做特殊照顾。



