C11的发展历史C11是C的第二个主要版本并且是从C98起的最重要更新。C11是C编程语言的一个重要版本于2011年正式发布。它引入了许多新特性和改进极大地增强了 C 的功能和易用性。下面介绍它的一些主要特性2列表初始化2.1C98传统的{}在C98中一般数组和结构体支持使用{}初始化。struct point { int x; int y; }; int main() { int arr1[5] {1,2,3,4,5}; point p { 1,2 }; return 0; }2.2C11中的{}struct point { int x; int y; }; class Date { public: Date(int year 1, int month 1, int day 1) :_year(year) , _month(month) , _day(day) { cout Date(int year int month , int day) endl; } Date(const Date d) :_year(d._year) ,_month(d._month) ,_day(d._day) { cout Date(const Date d) endl; } private: int _year; int _month; int _day; };C11后想统一初始化的方式试图一切对象皆可使用{}初始化{}初始化也叫列表初始化。内置类型支持自定义类型也支持自定义类型本质是类型转换中间会产生临时对象经过编译器优化后变成直接构造。//C11 //内置类型支持{}初始化 int x { 2 }; //自定义类型 //本质是{202511}构造出临时对象再拷贝给d1但是编译器优化为直接用{202511}构造d1 Date d1 { 2025,1,1 }; //这里的d2引用的是{202472}的临时对象 const Date d2 { 2024,7,2 }; //需要注意的是C98支持单参数时类型转换也可以不用加{} Date d3 { 2025 }; Date d4 2025;{}初始化可以省略//可以省略掉 int x2{ 2 }; point p1{ 1,2 }; Date d6{ 2025,1,2 }; const Date d7{ 2024,8,15 };C11的列表初始化在许多场景下会带来不少的便利如容器push/insert多参数构造的对象时用{}会很方便。vectorDate v; //有名对象传参 v.push_back(d6); //匿名对象传参 v.push_back(Date(2025, 1, 2)); //比起有名对象和匿名对象{}初始化更有性价比 v.push_back({ 2025,1,2 });2.3C11中的std::initializer_list上面的初始化已经很方便但是对于一个容器的初始化来说还是不太方便。比如一个vector对象我们想用N个值去初始化那么我们需要实现多个构造函数才能支持:vectorint v1{1,2,3}vectorint v2{1,2,3,4}vectorint v3{1,2,3,4,5};C11库中提供了一个std::initializer_list 这个类的本质是底层开一个数组将数据拷贝过来std::initializer_list 中有两个指针分别指向数组的开始和结束。这时只要我们的容器支持一个std::initializer_list的构造函数就可以支持多个值的{x1,x2,x3......}的初始化。STL中的 容器支持多个值构成的{x1,x2,x3,......}的初始化就是通过底层支持std::initiaalizer_list的构造实现的。如下图list和vector的构造函数中都增添了支持std::initializer_list的构造函数。vectorint v1 { 1,2,3,4,5 }; vectorint v2 { 1,2,3,4,5,6 }; //这里pair对象的{}初始化和map的initializer_list构造结合到一起了 mapstring, string dict { {sort,排序 },{string,字符串} };3右值引用和移动语义C98中就有引用的语法而C11中新增了右值引用的语法特性之前的引用叫做左值引用。无论左值引用还是右值引用都可以理解为是在给变量取别名。3.1左值和右值左值是一个表示数据的表达式如变量名或解引用 的指针一般是持久状态存储在内存中我们可以获取它的地址。左值可以出现在赋值符号的左边也可以是在右边。如果左值用const修饰就不能给它赋值但可以取它的地址。右值也是一个表示数据的表达式要么是常量或者是临时对象等右值可以出现在赋值符号的右边但不能出现在左边右值不能取地址。左值的英文简写为lvalue右值的英文简写为rvalue。传统认为它们分别是left value、right value 的缩写。现代C中lvalue被解释为loactor value的缩写可意为存储在内存中、有明确存储地址可以取地址的对象而rvalue被解释为read value指的是那些可以提供数据值但是不可以寻址例如临时变量常量存储于寄存器中的变量等也就是说左值和右值的核心区别就是能否取地址。//左值可以取地址 //以下均为左值 int* p new int(0); int b 1; const int c b; *p 10; string s(1111111); s[0] x; double x 1.1, y 2.2; //右值不能取地址 //以下几个均为右值 10; x y; string(111111);3.2左值引用和右值引用Type r1xType r2y。其中第一个语句就是左值引用 本质是给左值取别名。同理第二个语句就是给右值引用本质是给右值取别名。左值引用不能直接引用 右值需加上const修饰。//左值可以取地址 //以下均为左值 int* p new int(0); int b 1; const int c b; *p 10; string s(1111111); s[0] x; double x 1.1, y 2.2; //右值不能取地址 //以下几个均为右值 10; x y; string(111111);//左值引用给左值取别名int r1 b; int* r2 p; int r3 *p; string r4 s; char r5 s[0];//左值引用不能直接引用右值需加上cosntconst int rx1 10; const double rx2 x y; const string rx3 string(111111);右值引用不能直接引用 左值但可以引用move(左值。//左值可以取地址 //以下均为左值 int* p new int(0); int b 1; const int c b; *p 10; string s(1111111); s[0] x; double x 1.1, y 2.2; //右值不能取地址 //以下几个均为右值 10; x y; string(111111);//右值引用int rr1 10; double rr2 x y; string rr3 string(111111);//右值引用不能直接引用 左值但可以引用 move(左值)int rrx1 move(b); int* rrx2 move(p); int rrx3 move(*p); string rrx4 (move)(s); string rrx5 (string)s;move是库里面的一个函数模板本质内部做了强制类型转换涉及到一些引用折叠的知识