C++11概览与统一初始化

C++11是个分水岭。在这之前,C++标准委员会花了8年时间打磨,最终在2011年8月发布。它最初被叫做C++0x,因为原计划在2010年前推出,结果一拖再拖。C++11之后的节奏就稳了------每3年一个版本,C++14、17、20,规律迭代。

标准更新的动力很朴素:标准化既有实践,并提升抽象能力。比如列表初始化,就是想用一套语法覆盖所有初始化场景,省得你费心记各种形式的区别。

目录

[1. 从C++98的{}到C++11的统一初始化](#1. 从C++98的{}到C++11的统一初始化)

[2. std::initializer_list:让花括号更强大](#2. std::initializer_list:让花括号更强大)


1. 从C++98的{}到C++11的统一初始化

C++98里,花括号只能初始化数组和POD结构体:

cpp

复制代码
int arr[] = {1, 2, 3, 4, 5};
int arr2[5] = {0};
struct Point { int _x; int _y; };
Point p = {1, 2};

到了C++11,情况变了。一切对象都可以用{}初始化,内置类型、自定义类型、容器,一视同仁。甚至可以把等号省掉:

cpp

复制代码
int x1 = {2};
int x2{2};
Point p1{1, 2};
const Point& p2 = {1, 2};  // 引用绑定临时对象

class Date {
public:
    Date(int year = 1, int month = 1, int day = 1)
        : _year(year), _month(month), _day(day) { }
private:
    int _year, _month, _day;
};

Date d1 = {2025, 1, 1};    // 等价于 Date d1{2025, 1, 1}
const Date& d2 = {2024, 7, 25};  // 临时对象生命周期延长

这种写法背后发生了类型转换:{2025,1,1}会构造一个Date临时对象,再去拷贝给目标。但现代编译器会直接优化成原地构造,拷贝构造被消掉了。你可以自己加打印验证------拷贝构造不会被调用。

使用容器时,这种写法的便利性更明显:

cpp

复制代码
vector<Date> v;
v.push_back({2025, 1, 1});   // 比push_back(Date(2025,1,1))利落

2. std::initializer_list:让花括号更强大

上面的写法已经挺方便了,但还有一个需求没解决:用一堆值直接初始化容器。

cpp

复制代码
vector<int> v1 = {1, 2, 3, 4, 5};
vector<int> v2 = {1, 2, 3, 4, 5, 6, 7};

要支持这种用法,以前得写多个不同参数个数的构造函数。C++11通过std::initializer_list一劳永逸地解决了这个问题。

initializer_list内部可以理解为在栈上分配了一个临时数组,存两个指针(开始和结束),支持迭代器遍历。当你写下{1,2,3}时,编译器会为你构造一个initializer_list<int>对象。

cpp

复制代码
auto il = {10, 20, 30};  // il 类型为 initializer_list<int>
cout << sizeof(il) << endl;  // 典型实现为两个指针大小

STL容器都新增了接受initializer_list的构造函数和赋值运算符:

cpp

复制代码
vector(initializer_list<value_type> il,
       const allocator_type& alloc = allocator_type());
vector& operator=(initializer_list<value_type> il);
// list, map 同理

这样,任意多个值的初始化只需要一份实现:

cpp

复制代码
template<class T>
class my_vector {
public:
    my_vector(initializer_list<T> l) {
        for (auto e : l)
            push_back(e);
    }
    // ...
};

于是可以这样写:

cpp

复制代码
vector<int> v1({1,2,3,4,5});
vector<int> v2 = {1,2,3,4,5};
const vector<int>& v3 = {1,2,3,4,5};

map<string, string> dict = {{"sort", "排序"}, {"string", "字符串"}};

v1 = {10,20,30,40,50};   // initializer_list版本的赋值

值得注意的是,v1({1,2,3,4,5})是直接构造,v2 = {1,2,3,4,5}则是构造临时对象再通过拷贝/移动初始化v2,但编译器通常会优化成直接构造。两者语义上有细微差别,但实际运行效果往往一致。

列表初始化背后,本质是C++11对"统一抽象"的执念。一套语法,覆盖所有初始化场景,降低心智负担,这方向没错。

相关推荐
笨蛋不要掉眼泪1 小时前
Java并发编程:内存可见性与synchronized同步机制
java·开发语言·并发
爱喝水的鱼丶1 小时前
SAP-ABAP:数据类型与数据对象(8篇) 第四篇:关系映射篇——从类型定义到对象实例的转化逻辑
开发语言·数据库·学习·sap·abap
吃着火锅x唱着歌1 小时前
深度探索C++对象模型 学习笔记 第五章 构造、解构、拷贝语意学(1)
c++·笔记·学习
水无痕simon2 小时前
1. Guava 介绍
开发语言·python·guava
AI科技星2 小时前
全域数学公理:基于32维超复数与易经卦爻的宇宙大一统理论(整理版)
c语言·开发语言·线性代数·量子计算·agi
之歆2 小时前
DAY_13JavaScript DOM 操作完全指南:实战案例、性能优化与业务价值(下)
开发语言·前端·javascript·性能优化·ecmascript
承渊政道2 小时前
【贪心算法】(经典实战应用解析(五):单调递增的数字、坏了的计算器、合并区间、⽆重叠区间、⽤最少数量的箭引爆⽓球)
数据结构·c++·leetcode·贪心算法·排序算法·动态规划·哈希算法
Brilliantwxx2 小时前
【C++】深度剖析 · 继承 (虚基表+虚函数表)
开发语言·c++
砍材农夫2 小时前
物联网 基于netty构建mqtt协议规范(发布/订阅模式)
java·开发语言·物联网·netty