C++11 & C++14 & C++17 常用新特性总结
GCC编译器(从编译器GCC4.8.X的版本完全支持)
(1)目前C++11特性,之前成为C++0X特性,从GCC4.3的后续版本中逐步对C++11进行支持。
(2)从官方信息可以看到,目前从完全对C++11特性进行支持的是从编译器GCC4.8.X的版本。
参考网址:https://gcc.gnu.org/projects/cxx-status.html#cxx11
编译的时候加上参数:
1 | -std=c++11 |
C+11新特性
nullptr
传统 C++ 会把 NULL、0 视为同一种东西,这取决于编译器如何定义NULL,有些编译器会将 NULL 定义为 ((void*)0),有些则会直接将其定义为 0.
C++ 不允许直接将 void * 隐式转换到其他类型,但如果 NULL 被定义为 ((void*)0),那么当编译char *ch = NULL;时,NULL 只好被定义为 0。
这样就会导致重载特性混乱,比如foo(NULL)调用的是foo(int)
1 | void foo(char *); |
类型推导 auto和decltype
auto
常见用法:
1 | for(vector<int>::const_iterator it = vec.begin(); it != vec.end(); it++) // 不使用推导 |
错误用法:
1 | int foo(auto i,auto j); // 传参数,类型未定义,无法重载,无法通过编译 |
decltype
为了解决auto只能对变量推导的缺陷,所以decltype的用法是 decltype(表达是)
1 | auto i = 4; |
拖尾类型返回
1 | template<typename R,typename T,typename U> //返回类型也要指定 |
区间迭代
常见用法:
1 | for (vector<int>::const_iterator it = vec.begin(); it != vec.end(); it++) // 不使用推导 |
初始化列表
c++提供了统一的语法初始化任意的对象
1 | struct A { |
模板增强
尖括号 “>”
在传统 C++ 的编译器中,>>一律被当做右移运算符来进行处理。C++11 开始,连续的右尖括号将变得合法,并且能够顺利通过编译。
1 | std::vector<std::vector<int>> wow; |
构造函数
委托构造
构造函数可以在同一个类中一个构造函数调用另一个构造函数
1 | class Base { |
继承构造
使用继承构造之前
1 | struct A |
C++11的继承构造后
1 | struct A |
Lambda 表达式
Lambda 表达式,实际上就是提供了一个类似匿名函数的特性
1 | [ caputrue ] ( params ) opt -> ret { body; }; |
- capture是捕获列表;
- params是参数表;(选填)
- opt是函数选项;可以填mutable,exception,attribute(选填)
mutable说明lambda表达式体内的代码可以修改被捕获的变量,并且可以访问被捕获的对象的non-const方法。
exception说明lambda表达式是否抛出异常以及何种异常。
attribute用来声明属性。 - ret是返回值类型(拖尾返回类型)。(选填)
- body是函数体。
捕获列表:lambda表达式的捕获列表精细控制了lambda表达式能够访问的外部变量,以及如何访问这些变量。
1) []不捕获任何变量。
2) [&]捕获外部作用域中所有变量,并作为引用在函数体中使用(按引用捕获)。
3) [=]捕获外部作用域中所有变量,并作为副本在函数体中使用(按值捕获)。注意值捕获的前提是变量可以拷贝,且被捕获的变量在 lambda 表达式被创建时拷贝,而非调用时才拷贝。如果希望lambda表达式在调用时能即时访问外部变量,我们应当使用引用方式捕获。
1 | int a = 0; |
4) [=,&foo]按值捕获外部作用域中所有变量,并按引用捕获foo变量。
5) [bar]按值捕获bar变量,同时不捕获其他变量。
6) [this]捕获当前类中的this指针,让lambda表达式拥有和当前类成员函数同样的访问权限。如果已经使用了&或者=,就默认添加此选项。捕获this的目的是可以在lamda中使用当前类的成员函数和成员变量。
1 | class A |
注意f4,虽然按值捕获的变量值均复制一份存储在lambda表达式变量中,修改他们也并不会真正影响到外部,但我们却仍然无法修改它们。如果希望去修改按值捕获的外部变量,需要显示指明lambda表达式为mutable。被mutable修饰的lambda表达式就算没有参数也要写明参数列表。
原因:lambda表达式可以说是就地定义仿函数闭包的“语法糖”。它的捕获列表捕获住的任何外部变量,最终会变为闭包类型的成员变量。按照C++标准,lambda表达式的operator()默认是const的,一个const成员函数是无法修改成员变量的值的。而mutable的作用,就在于取消operator()的const。
1 | int a = 0; |
lambda表达式是不能被赋值的:
1 | auto a = [] { cout << "A" << endl; }; |
闭包类型禁用了赋值操作符,但是没有禁用复制构造函数,所以你仍然可以用一个lambda表达式去初始化另外一个lambda表达式而产生副本。
在多种捕获方式中,最好不要使用[=]和[&]默认捕获所有变量。
1 | std::function<int(int)> add_x(int x) |
悬挂引用,返回了一个lambda表达式,参数x仅是一个临时变量,函数add_x调用后就被销毁了,但是返回的lambda表达式却引用了该变量,当调用这个表达式时,引用的是一个垃圾值,会产生没有意义的结果。
采用默认值捕获所有变量仍然有风险
1 | class Filter |
这个类中有一个成员方法,可以返回一个lambda表达式,这个表达式使用了类的数据成员divisor。而且采用默认值方式捕捉所有变量。lambda表达式无法捕捉divisor的副本,因为数据成员divisor对lambda表达式并不可见
错误
1 | std::function<bool(int)> getFilter() |
正确
1 | std::function<bool(int)> getFilter() |
实现函数回调,类似函数指针
1 | std::function<bool(int, int)> wrapper = [](int x, int y) { return x < y; }; |
最常用的是在STL算法中
1 | int value = 3; |
生成斐波那契数列,然后保存在数组中
1 | vector<int> v(10); |
当需要遍历容器并对每个元素进行操作时
1 | std::vector<int> v = { 1, 2, 3, 4, 5, 6 }; |
新增容器
std::array
std::forward_list
无序容器
元组 std::tuple
std::make_tuple: 构造元组
std::get: 获得元组某个位置的值
std::tie: 元组拆包
1 |
|
正则表达式
- 检查一个串是否包含某种形式的子串;
- 将匹配的子串替换;
- 从某个串中取出符合条件的子串。
1 |
|
语言级线程支持
std::mutex/std::unique_lock
std::future/std::packaged_task
std::condition_variable
代码编译需要使用 -pthread 选项
右值引用&&
- 消除两个对象交互时不必要的对象拷贝,节省运算存储资源,提高效率。
- 能够更简洁明确地定义泛型函数。
1 | class MyString { |
运行结果
1 | Copy Assignment is called! source: Hello |
1 | MyString(MyString&& str) { //转移构造函数 |
注:右值引用并不能阻止编译器在临时对象使用完之后将其释放掉的事实,所以转移构造函数
和转移赋值操作符重载函数
中都将_data
赋值为了NULL
,而且析构函数中保证了_data != NULL
才会释放。
std::move
std::move并不能移动任何东西,它唯一的功能是将一个左值强制转化为右值引用,继而可以通过右值引用使用该值,以用于移动语义。从实现上讲,std::move基本等同于一个类型转换:static_cast<T&&>(lvalue)
- C++ 标准库使用比如vector::push_back 等这类函数时,会对参数的对象进行复制,连数据也会复制.这就会造成对象内存的额外创建, 本来原意是想把参数push_back进去就行了,通过std::move,可以避免不必要的拷贝操作。
- std::move是将对象的状态或者所有权从一个对象转移到另一个对象,只是转移,没有内存的搬迁或者内存拷贝所以可以提高利用效率,改善性能.。
- 对指针类型的标准库对象并不需要这么做.
命名对象使用 std::move右值引用
既然编译器只对右值引用才能调用转移构造函数和转移赋值函数,又因为所有命名对象都只能是左值引用。 在这样的条件了,如果已知一个命名对象不再被使用而想对它调用转移构造函数和转移赋值函数,也就是把一个左值引用当做右值引用来使用,怎么做呢?标准库提供了函数 std::move,这个函数以非常简单的方式将左值引用转换为右值引用。
1 | void ProcessValue(int& i) { |
运行结果:
1 | LValue processed: 0 |
std::move在提高 swap 函数的的性能上非常有帮助
1 | template<class T> |
1 | template<class T> |
使用右值引用精确传递
1 | template<typename T> |
为了解决这种情况,使用右值引用
1 | template<typename T> |
智能指针
智能指针在C++11版本之后提供,包含在头文件
shared_ptr
shared_ptr多个指针指向相同的对象。shared_ptr使用引用计数,每一个shared_ptr的拷贝都指向相同的内存。每使用他一次,内部的引用计数加1,每析构一次,内部的引用计数减1,减为0时,自动删除所指向的堆内存。shared_ptr内部的引用计数是线程安全的,但是对象的读取需要加锁。
- 初始化。智能指针是个模板类,可以指定类型,传入指针通过构造函数初始化。也可以使用make_shared函数初始化。不能将指针直接赋值给一个智能指针,一个是类,一个是指针。例如std::shared_ptr
p4 = new int(1);的写法是错误的 - 拷贝和赋值。拷贝使得对象的引用计数增加1,赋值使得原对象引用计数减1,当计数为0时,自动释放内存。后来指向的对象引用计数加1,指向后来的对象。
- get函数获取原始指针
- 注意不要用一个原始指针初始化多个shared_ptr,否则会造成二次释放同一内存
- 注意避免循环引用,shared_ptr的一个最大的陷阱是循环引用,循环,循环引用会导致堆内存无法正确释放,导致内存泄漏。循环引用在weak_ptr中介绍。
unique_ptr
unique_ptr“唯一”拥有其所指对象,同一时刻只能有一个unique_ptr指向给定对象(通过禁止拷贝语义、只有移动语义来实现),unique_ptr指针与其所指对象的关系:在智能指针生命周期内,可以改变智能指针所指对象,如创建智能指针时通过构造函数指定、通过reset方法重新指定、通过release方法释放所有权、通过移动语义转移所有权。
1 |
|
weak_ptr
weak_ptr是为了配合shared_ptr而引入的一种智能指针,因为它不具有普通指针的行为,没有重载operator*和->,它的最大作用在于协助shared_ptr工作,像旁观者那样观测资源的使用情况。
weak_ptr可以从一个shared_ptr或者另一个weak_ptr对象构造,获得资源的观测权。但weak_ptr没有共享资源,它的构造不会引起指针引用计数的增加。
使用weak_ptr的成员函数use_count()可以观测资源的引用计数,另一个成员函数expired()的功能等价于use_count()==0,但更快,表示被观测的资源(也就是shared_ptr的管理的资源)已经不复存在。weak_ptr可以使用一个非常重要的成员函数lock()从被观测的shared_ptr获得一个可用的shared_ptr对象, 从而操作资源。但当expired()==true的时候,lock()函数将返回一个存储空指针的shared_ptr。
1 |
|
std::function
std::function 是一个可调用对象包装器,是一个类模板,可以容纳除了类成员函数指针之外的所有可调用对象,它可以用统一的方式处理函数、函数对象、函数指针,并允许保存和延迟它们的执行。
定义格式:std::function<函数类型>。
std::function可以取代函数指针的作用,因为它可以延迟函数的执行,特别适合作为回调函数使用。它比普通函数指针更加的灵活和便利。
std::bind
可将std::bind函数看作一个通用的函数适配器,它接受一个可调用对象,生成一个新的可调用对象来“适应”原对象的参数列表。
std::bind将可调用对象与其参数一起进行绑定,绑定后的结果可以使用std::function保存。std::bind主要有以下两个作用:
将可调用对象和其参数绑定成一个防函数;
只绑定部分参数,减少可调用对象传入的参数。
注意:
(1)bind预先绑定的参数需要传具体的变量或值进去,对于预先绑定的参数,是pass-by-value的
(2)对于不事先绑定的参数,需要传std::placeholders进去,从_1开始,依次递增。placeholder是pass-by-reference的
(3)bind的返回值是可调用实体,可以直接赋给std::function对象
(4)对于绑定的指针、引用类型的参数,使用者需要保证在可调用实体调用之前,这些参数是可用的
(5)类的this可以通过对象或者指针来绑定
1 | int Func(int x, int y); |
1 | double my_divide (double x, double y) {return x/y;} |
1 | struct Foo { |
std::forward
需要一种方法能够按照参数原来的类型转发到另一个函数,这种转发类型称为完美转发。
完美转发(Perfect Forwarding),是指在函数模板中,完全依照模板的参数的类型(即保持参数的左值、右值特征),将参数传递给函数模板中调用的另外一个函数。C++11中提供了这样的一个函数std::forward,它是为转发而生的,不管参数是T&&这种未定的引用还是明确的左值引用或者右值引用,它会按照参数本来的类型转发。
1 |
|
std::move没有move任何东西,std::forward没有转发任何东西。在运行期,它们没有做任何事情。它们没有产生需要执行的代码,一byte都没有。
std::move和std::forward只不过就是执行cast的两个函数(实际上是函数模板)。std::move无条件地把它的参数转换成一个右值,而std::forward只在特定条件满足的情况下执行这个转换。
delete
1 | 为了能够让程序员显式的禁用某个函数,C++11 标准引入了一个新特性:"=delete"函数。程序员只需在函数声明后上“=delete;”,就可将该函数禁用。 |
1 | class MyClass |
enable_shared_from_this
定义
std::enable_shared_from_this 能让一个对象(假设其名为 t ,且已被一个 std::shared_ptr 对象 pt 管理)安全地生成其他额外的 std::shared_ptr 实例(假设名为 pt1, pt2, … ) ,它们与 pt 共享对象 t 的所有权。
若一个类 T 继承 std::enable_shared_from_this
使用场合
当类A被share_ptr管理,且在类A的成员函数里需要把当前类对象作为参数传给其他函数时,就需要传递一个指向自身的share_ptr。
- 为何不直接传递this指针
使用智能指针的初衷就是为了方便资源管理,如果在某些地方使用智能指针,某些地方使用原始指针,很容易破坏智能指针的语义,从而产生各种错误。
可以直接传递share_ptr
么? 答案是不能,因为这样会造成2个非共享的share_ptr指向同一个对象,未增加引用计数导对象被析构两次。
错误:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Bad
{
public:
std::shared_ptr<Bad> getptr() {
return std::shared_ptr<Bad>(this);
}
~Bad() { std::cout << "Bad::~Bad() called" << std::endl; }
};
int main()
{
// 错误的示例,每个shared_ptr都认为自己是对象仅有的所有者
std::shared_ptr<Bad> bp1(new Bad());
std::shared_ptr<Bad> bp2 = bp1->getptr();
// 打印bp1和bp2的引用计数
std::cout << "bp1.use_count() = " << bp1.use_count() << std::endl;
std::cout << "bp2.use_count() = " << bp2.use_count() << std::endl;
} // Bad 对象将会被删除两次正确:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
struct Good : std::enable_shared_from_this<Good> // 注意:继承
{
public:
std::shared_ptr<Good> getptr() {
return shared_from_this();
}
~Good() { std::cout << "Good::~Good() called" << std::endl; }
};
int main()
{
// 大括号用于限制作用域,这样智能指针就能在system("pause")之前析构
{
std::shared_ptr<Good> gp1(new Good());
std::shared_ptr<Good> gp2 = gp1->getptr();
// 打印gp1和gp2的引用计数
std::cout << "gp1.use_count() = " << gp1.use_count() << std::endl;
std::cout << "gp2.use_count() = " << gp2.use_count() << std::endl;
}
system("pause");为何会出现这种使用场合
因为在异步调用中,存在一个保活机制,异步函数执行的时间点我们是无法确定的,然而异步函数可能会使用到异步调用之前就存在的变量。为了保证该变量在异步函数执期间一直有效,我们可以传递一个指向自身的share_ptr给异步函数,这样在异步函数执行期间share_ptr所管理的对象就不会析构,所使用的变量也会一直有效了(保活)。
mutable
在C++中,mutable也是为了突破const的限制而设置的。被mutable修饰的变量,将永远处于可变的状态,即使在一个const函数中。
我们知道,被const关键字修饰的函数的一个重要作用就是为了能够保护类中的成员变量。即:该函数可以使用类中的所有成员变量,但是不能修改他们的值。然而,在某些特殊情况下,我们还是需要在const函数中修改类的某些成员变量,因为要修改的成员变量与类本身并无多少关系,即使修改了也不会对类造成多少影响。当然,你可以说,你可以去掉该函数的const关键字呀!但问题是,我只想修改某个成员变量,其余成员变量仍然希望被const保护。
using各种用法
1 | /*定义别名*/ |
不想要使用默认的拷贝构造函数或赋值函数
1.新增auto、decltype关键字,二者相似又有区别
2.新增char16_t、char32_t、long long int类型
3.新增constexpr编译时常量表达式
4.新增default、delete、override、final说明符
5.新增delegating constructors委托构造函数
6.新增std::initializer_list初始化列表、uniform initialization统一初始化
7.新增Enum class枚举类、extend templates拓展模板、type可用于模板
8.新增Lambda表达式
9.新增nullptr、foreach、r-value右值,tuple元组
10.新增移动意义,包括move constructor移动构造、move assign移动赋值
11.新增static_assert编译时检查
12.新增智能指针std::unique_ptr、std::share_ptr、std::weak_ptr,废弃std::auto_ptr
C++14新特性:
1.新增聚合成员初始化
2.新增二进制文字、数字分隔符
3.废弃attribute
4.新增函数返回值推断
5.新增constexpr函数
6.新增变体模板
7.新增标准用户定义的文字
8.新增std::make_unique,用于创建std::unique_ptr、
参考信息
C++2a 功能特性 | 提案 | 版本 | GCC | Clang | MSVC | EDG eccp | Intel C++ | IBM XLC++ | Sun/Oracle C++ | Embarcadero C++ Builder | Cray | Portland Group (PGI) | [折叠] |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
允许 lambda 捕获 [=, this] |
P0409R2 | c++2a-lang | 8 | 6 | 5.1 | ||||||||
__VA_OPT__ |
P0306R4 | c++2a-lang | 8 (部分)* | 6 | 5.1 | ||||||||
指派初始化器 | P0329R4 | c++2a-lang | 4.7 (部分)* 8 | 3.0 (部分)* | 5.1 | ||||||||
泛型 lambda 的模板形参列表 | P0428R2 | c++2a-lang | 8 | 5.1 | |||||||||
位域的默认成员初始化器 | P0683R1 | c++2a-lang | 8 | 6 | 5.1 | ||||||||
类模板实参推导中的 initializer_list 构造函数 | P0702R1 | c++2a-lang | 8 | 6 | 19.14* | 5.0 | |||||||
const& 限定的成员指针 | P0704R1 | c++2a-lang | 8 | 6 | 5.1 | ||||||||
概念 (concept) | P0734R0 | c++2a-lang | 6 (仅 TS) | ||||||||||
不求值语境中的 lambda | P0315R4 | c++2a-lang | 9 | ||||||||||
三路比较运算符 | P0515R3 | c++2a-lang | 8 (部分)* | 19.20* | |||||||||
简化隐式 lambda 捕获 | P0588R1 | c++2a-lang | 8 | ||||||||||
基于范围的 for 的初始化语句 | P0614R1 | c++2a-lang | 9 | 8 | |||||||||
可默认构造且可赋值的无状态 lambda | P0624R2 | c++2a-lang | 9 | 8 | 5.1 | ||||||||
与预置的复制构造函数的 const 不匹配 | P0641R2 | c++2a-lang | 9 | 8 | 5.1 | ||||||||
特化上的访问检查 | P0692R1 | c++2a-lang | 是 | 8 (部分)* | |||||||||
ADL 与不可见的函数模板 | P0846R0 | c++2a-lang | 9 | ||||||||||
令 constexpr 函数的实例化较不贪婪 | P0859R0 | c++2a-lang | 5.2 (部分)* 9 | ||||||||||
属性 [[likely]] 与 [[unlikely]] |
P0479R5 | c++2a-lang | 9 | 5.1 | |||||||||
使 typename 更可选 |
P0634R3 | c++2a-lang | 9 | ||||||||||
Lambda 初始化捕获中的包展开 | P0780R2 | c++2a-lang | 9 | ||||||||||
属性 [[no_unique_address]] |
P0840R2 | c++2a-lang | 9 | 5.1 | |||||||||
契约 | P0542R5 | c++2a-lang | |||||||||||
销毁的 operator delete | P0722R3 | c++2a-lang | 9 | 6 | |||||||||
非类型模板形参中的类类型 | P0732R2 | c++2a-lang | 9 | ||||||||||
explicit(bool) | P0892R2 | c++2a-lang | 9 | 5.1 | |||||||||
整合功能特性测试宏 | P0941R2 | c++2a-lang | 5 | 3.4 | 19.15* | 5.0 | |||||||
禁止聚合体有用户声明的构造函数 | P1008R1 | c++2a-lang | 9 | 8 | 5.1 | ||||||||
constexpr 虚函数 | P1064R0 | c++2a-lang | 9 | 5.1 | |||||||||
char8_t |
P0482R6 | c++2a-lang | 9 | 7 | |||||||||
std::is_constant_evaluated() | P0595R2 | c++2a-lang | 9 | ||||||||||
constexpr try -catch 代码块 |
P1002R1 | c++2a-lang | 9 | 8 | 5.1 | ||||||||
立即函数 | P1073R3 | c++2a-lang | 5.1 | ||||||||||
嵌套内联命名空间 | P1094R2 | c++2a-lang | 9 | 8 | 5.1 | ||||||||
constexpr 的 dynamic_cast 和多态 typeid |
P1327R1 | c++2a-lang | 5.1 | ||||||||||
在 constexpr 中改变联合体的活跃成员 | P1330R0 | c++2a-lang | 9 | 5.1 | |||||||||
结构化绑定的扩展 | P1091R3 P1381R1 | c++2a-lang | |||||||||||
更强的 Unicode 要求 | P1041R4 P1139R2 | c++2a-lang | 是 | ||||||||||
参数化的聚合体初始化 | P0960R3 | c++2a-lang | |||||||||||
模块 (module) | P1103R3 | c++2a-lang | 8 (部分) | ||||||||||
协程 (coroutine) | P0912R5 | c++2a-lang | 8 (部分) | ||||||||||
std::endian | P0463R1 | c++2a | 8 | 7 | N/A | ||||||||
std::remove_cvref | P0550R2 | c++2a | 9 | 6 | 19.20* | N/A | |||||||
扩展 std::make_shared 以支持数组 | P0674R1 | c++2a | N/A | ||||||||||
原子性浮点算术 | P0020R6 | c++2a | N/A | ||||||||||
同步缓冲的 ostream | P0053R7 | c++2a | N/A | ||||||||||
与 的 constexpr |
P0202R3 | c++2a | 8 | N/A | |||||||||
的更多 constexpr |
P0415R1 | c++2a | 9 | N/A | |||||||||
字符串前缀与后缀检查 | P0457R2 | c++2a | 9 | 6 | N/A | ||||||||
operator<=> 的库支持 |
P0515R3 | c++2a | 7 | 19.20* | N/A | ||||||||
转换指针为裸指针的工具 | P0653R2 | c++2a | 8 | 6 | N/A | ||||||||
原子性的 shared_ptr 与 weak_ptr | P0718R2 | c++2a | N/A | ||||||||||
std::span | P0122R7 | c++2a | 7 | N/A | |||||||||
日历与时区 | P0355R7 | c++2a | 7 | N/A | |||||||||
P0754R2 | c++2a | 9 | 7 | N/A | |||||||||
std::atomic_ref | P0019R8 | c++2a | N/A | ||||||||||
整数的 2 的幂的运算 | P0556R3 | c++2a | 9 | N/A | |||||||||
std::bit_cast() | P0476R2 | c++2a | N/A | ||||||||||
std::destroying_delete | P0722R3 | c++2a | 9 | N/A | |||||||||
概念库 | P0898R3 | c++2a | N/A | ||||||||||
一致的容器擦除 | P1209R0 | c++2a | 9 | 8 | N/A | ||||||||
C++2a 功能特性 | 提案 | 版本 | GCC | Clang | MSVC | EDG eccp | Intel C++ | IBM XLC++ | Sun/Oracle C++ | Embarcadero C++ Builder | Cray | Portland Group (PGI) |
C++17 功能特性
C++17 功能特性 | 提案 | 版本 | GCC | Clang | MSVC | EDG eccp | Intel C++ | IBM XLC++ | Sun/Oracle C++ | Embarcadero C++ Builder | Cray | Portland Group (PGI) | [折叠] |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
直接列表初始化的新 auto 规则 | N3922 | c++17-lang | 5 | 3.8 | 19.0* | 4.10.1 | 17.0 | 17.7 | |||||
无消息的 static_assert | N3928 | c++17-lang | 6 | 2.5 | 19.10* | 4.12 | 18.0 | 17.7 | |||||
模板模板形参中的 typename |
N4051 | c++17-lang | 5 | 3.5 | 19.0* | 4.10.1 | 17.0 | 17.7 | |||||
移除三标符 | N4086 | c++17-lang | 5 | 3.5 | 16.0* | 5.0 | |||||||
嵌套命名空间定义 | N4230 | c++17-lang | 6 | 3.6 | 19.0* | 4.12 | 17.0 | 17.7 | |||||
命名空间和枚举项的属性 | N4266 | c++17-lang | 4.9 (命名空间) / 6 (枚举项) | 3.6 | 19.0* | 4.11 | 17.0 | 17.7 | |||||
u8 字符字面量 |
N4267 | c++17-lang | 6 | 3.6 | 19.0* | 4.11 | 17.0 | 17.7 | |||||
允许所有非类型模板实参的常量求值 | N4268 | c++17-lang | 6 | 3.6 | 19.12* | 5.0 | |||||||
折叠表达式 | N4295 | c++17-lang | 6 | 3.6 | 19.12* | 4.14 | 19.0 | 18.1 | |||||
移除 register 关键字的已弃用用法 | P0001R1 | c++17-lang | 7 | 3.8 | 19.11* | 4.13 | 18.0 | 17.7 | |||||
移除已弃用的 operator++(bool) | P0002R1 | c++17-lang | 7 | 3.8 | 19.11* | 4.13 | 18.0 | 17.7 | |||||
从 C++17 移除已弃用的异常规定 | P0003R5 | c++17-lang | 7 | 4 | 19.10* | 4.14 | 19.0 | ||||||
令异常规定为类型系统的一部分 | P0012R1 | c++17-lang | 7 | 4 | 19.12* | 4.14 | 19.0 | ||||||
有基类的类的聚合初始化 | P0017R1 | c++17-lang | 7 | 3.9 | 19.14* | 5.0 | |||||||
*this 的 lambda 捕获 |
P0018R3 | c++17-lang | 7 | 3.9 | 19.11* | 4.14 | 19.0 | 18.1 | |||||
使用属性命名空间而不重复 | P0028R4 | c++17-lang | 7 | 3.9 | 19.11* | 4.13 | 18.0 | 17.7 | |||||
过对齐数据的动态内存分配 | P0035R4 | c++17-lang | 7 | 4 | 19.12* | 4.14 | |||||||
一元折叠表达式和空形参包 | P0036R0 | c++17-lang | 6 | 3.9 | 19.12* | 4.14 | |||||||
预处理器条件中的 __has_include | P0061R1 | c++17-lang | 5 | 是 | 19.11* | 4.13 | 18.0 | 17.7 | |||||
类模板实参推导 | P0091R3 | c++17-lang | 7 | 5 | 19.14* | 5.0 | 19.1 | ||||||
具有 auto 类型的非类型模板形参 |
P0127R2 | c++17-lang | 7 | 4 | 19.14* | 5.0 | 19.1 | ||||||
有保证的复制消除 | P0135R1 | c++17-lang | 7 | 4 | 19.13* | 5.0 | 19.1 | ||||||
继承构造函数的新规定 (DR1941 等) | P0136R1 | c++17-lang | 7 | 3.9 | 19.14* | ||||||||
替换含引用成员的类对象 | P0137R1 | c++17-lang | 7 | 6 | 19.14* | 5.0 | |||||||
枚举的直接列表初始化 | P0138R2 | c++17-lang | 7 | 3.9 | 19.11* | 4.14 | 18.0 | ||||||
更严格的表达式求值顺序 | P0145R3 | c++17-lang | 7 | 4 | 19.14* | 5.0 | |||||||
constexpr lambda 表达式 | P0170R1 | c++17-lang | 7 | 5 | 19.11* | 4.14 | 19.0 | 18.1 | |||||
基于范围 for 的相异 begin 和 end 类型 | P0184R0 | c++17-lang | 6 | 3.9 | 19.10* | 4.12 | 18.0 | 17.7 | |||||
[[fallthrough]] 属性 |
P0188R1 | c++17-lang | 7 | 3.9 | 19.10* | 4.13 | 18.0 | 17.7 | |||||
[[nodiscard]] 属性 |
P0189R1 | c++17-lang | 7 | 3.9 | 19.11* | 4.13 | 18.0 | 17.7 | |||||
using 声明中的包展开 | P0195R2 | c++17-lang | 7 | 4 | 19.14* | 5.0 | |||||||
[[maybe_unused]] 属性 |
P0212R1 | c++17-lang | 7 | 3.9 | 19.11* | 4.13 | 18.0 | 17.7 | |||||
结构化绑定 | P0217R3 | c++17-lang | 7 | 4 | 19.11* | 4.14 | 19.0 | 18.1 | |||||
十六进制浮点字面量 | P0245R1 | c++17-lang | 3.0 | 是 | 19.11* | 4.13 | 18.0 | 17.7 | |||||
忽略未知属性 | P0283R2 | c++17-lang | 是 | 3.9 | 19.11* | 4.13 | 18.0 | 17.7 | |||||
constexpr if 语句 | P0292R2 | c++17-lang | 7 | 3.9 | 19.11* | 4.14 | 19.0 | 18.1 | |||||
if 和 switch 的初始化语句 | P0305R1 | c++17-lang | 7 | 3.9 | 19.11* | 4.14 | 18.0 | 18.1 | |||||
内联变量 | P0386R2 | c++17-lang | 7 | 3.9* | 19.12* | 4.14 | 19.0 | 18.1 | |||||
DR :模板模板实参的匹配排除了兼容的模板 | P0522R0 | c++17-lang | 7 | 4 | 19.12* | 5.0 | |||||||
std::uncaught_exceptions | N4259 | c++17 | 6 | 3.7 | 19.0* | N/A | N/A | N/A | |||||
改进 std::pair 和 std::tuple | N4387 | c++17 | 6 | 4 | 19.0* | N/A | N/A | N/A | |||||
std::any | P0220R1 | c++17 | 7 | 4 | 19.10* | N/A | N/A | N/A | |||||
std::variant | P0088R3 | c++17 | 7 | 4 | 19.10* | N/A | N/A | N/A | |||||
std::optional | P0220R1 | c++17 | 7 | 4 | 19.10* | N/A | N/A | N/A | |||||
std::shared_mutex (无时限) | N4508 | c++17 | 6 | 3.7 | 19.0* | N/A | N/A | N/A | |||||
std::string_view | N3921 | c++17 | 7 | 4 | 19.10* | N/A | N/A | N/A | |||||
并行 TS 的标准化 | P0024R2 | c++17 | 19.14* (部分) | N/A | 18.0* | N/A | |||||||
C++17 应当指代 C11 而不是 C99 | P0063R3 | c++17 | 9 | 7 | 19.0* (部分)* | N/A | N/A | N/A | |||||
初等字符串转换 | P0067R5 | c++17 | 8 (无浮点) | 19.14(无浮点) 19.15 | N/A | N/A | N/A | ||||||
数学特殊函数 | P0226R1 | c++17 | 7 | 19.14* | N/A | N/A | N/A | ||||||
接合 map 和 set | P0083R3 | c++17 | 7 | 8 | 19.12* | N/A | N/A | N/A | |||||
硬件干涉大小 | P0154R1 | c++17 | 19.11* | N/A | N/A | N/A | |||||||
std::filesystem | P0218R1 | c++17 | 8 | 7 | 19.14* | N/A | N/A | N/A | |||||
std::byte | P0298R3 | c++17 | 7 | 5 | 19.11* | N/A | N/A | N/A | |||||
C++17 功能特性 | 提案 | 版本 | GCC | Clang | MSVC | EDG eccp | Intel C++ | IBM XLC++ | Sun/Oracle C++ | Embarcadero C++ Builder | Cray | Portland Group (PGI) |
C++14 功能特性
C++14 功能特性 | 提案 | 版本 | GCC | Clang | MSVC | EDG eccp | Intel C++ | IBM XLC++ | Sun/Oracle C++ | Embarcadero C++ Builder | Cray | Portland Group (PGI) | [折叠] |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
按语境转换的遣词调整 | N3323 | c++14-lang | 4.9 | 3.4 | 18.0* | 4.9 | 16.0 | 13.1.2* | 5.15 | 8.6 | 16.1 | ||
二进制字面量 | N3472 | c++14-lang | 4.3/4.9 | 2.9 | 19.0* | 4.10 | 11.0 | 13.1.2* | 5.14 | 8.6 | 2015 | ||
decltype(auto) ,普通函数的返回类型推导 | N3638 | c++14-lang | 4.8/4.9 | 3.3/3.4 | 19.0* | 4.9 | 15.0 | 13.1.2* | 5.15 | 8.6 | 16.1 | ||
带初始化/泛化的 lambda 捕获 (init-capture) | N3648 | c++14-lang | 4.5/4.9 | 3.4 | 19.0* | 4.10 | 15.0 | 5.15 | 8.6 | 16.1 | |||
泛型(多态) lambda 表达式 | N3649 | c++14-lang | 4.9 | 3.4 | 19.0* | 4.10 | 16.0 | 13.1.2* | 5.15 | 8.6 | 16.1 | ||
变量模板 | N3651 | c++14-lang | 5 | 3.4 | 19.0* | 4.11 | 17.0 | 13.1.2* | 5.15 | 8.6 | 17.4 | ||
扩展的 constexpr | N3652 | c++14-lang | 5 | 3.4 | 19.10* | 4.11 | 17.0 | 13.1.2* | 5.15 | 8.6 | 17.4 | ||
成员初始化器与聚合体 (NSDMI) | N3653 | c++14-lang | 5 | 3.3 | 19.10* | 4.9 | 16.0 | 5.14 | 8.6 | 16.1 | |||
澄清内存分配(分配的免除/融合) | N3664 | c++14-lang | N/A | 3.4 | N/A | N/A | N/A | 8.6 | 17.4 | ||||
[[deprecated]] 属性 |
N3760 | c++14-lang | 4.9 | 3.4 | 19.0* | 4.9 | 15.0* 16.0 | 13.1.2* | 5.14 | 8.6 | 16.1 | ||
具大小解分配 | N3778 | c++14-lang | 5 | 3.4 | 19.0* | 4.10.1 | 17.0 | 5.14 | 8.6 | 16.1 | |||
单引号作为数位分隔符 | N3781 | c++14-lang | 4.9 | 3.4 | 19.0* | 4.10 | 16.0 | 13.1.2* | 5.14 | 8.6 | 2015 | ||
std::result_of 与 SFINAE | N3462 | c++14 | 5 | 是 | 19.0* | N/A | N/A | 5.15 | 是 | 8.6 | N/A | ||
的 constexpr |
N3302 | c++14 | 5 | 3.4 | 19.0* | N/A | N/A | 5.15 | 8.6 | N/A | |||
的 constexpr |
N3469 | c++14 | 5 | 3.4 | 19.0* | N/A | N/A | 5.15 | 8.6 | N/A | |||
的 constexpr |
N3470 | c++14 | 5 | 3.4 | 19.0* | N/A | N/A | 5.15 | 8.6 | N/A | |||
、 和 的 constexpr |
N3471 | c++14 | 5 | 3.4 | 19.0* | N/A | N/A | 5.15 | 8.6 | N/A | |||
改进的 std::integral_constant | N3545 | c++14 | 5 | 3.4 | 19.0* | N/A | N/A | 5.15 | 8.6 | N/A | |||
和 的用户定义字面量 | N3642 | c++14 | 5 | 3.4 | 19.0* | N/A | N/A | 5.15 | 8.6 | N/A | |||
空向前迭代器 | N3644 | c++14 | 5* | 3.4 | 19.0* | N/A | N/A | 5.15 | 8.6 | N/A | |||
std::quoted | N3654 | c++14 | 5 | 3.4 | 19.0* | N/A | N/A | 5.15 | 8.6 | N/A | |||
异质关联查找 | N3657 | c++14 | 5 | 3.4 | 19.0* | N/A | N/A | 5.15 | 8.6 | N/A | |||
std::integer_sequence | N3658 | c++14 | 5 | 3.4 | 19.0* | N/A | N/A | 5.15 | 8.6 | N/A | |||
std::shared_timed_mutex | N3659 | c++14 | 5 | 3.4 | 19.0* | N/A | N/A | 5.15 | 8.6 | N/A | |||
std::exchange | N3668 | c++14 | 5 | 3.4 | 19.0* | N/A | N/A | 5.15 | 8.6 | N/A | |||
修正无 const 的 constexpr 成员函数 |
N3669 | c++14 | 5 | 3.4 | 19.0* | N/A | N/A | 5.15 | 8.6 | N/A | |||
std::get() | N3670 | c++14 | 5 | 3.4 | 19.0* | N/A | N/A | 5.15 | 8.6 | N/A | |||
双范围的 std::equal 、 std::is_permutation 、 std::mismatch | N3671 | c++14 | 5 | 3.4 | 19.0* | N/A | N/A | 5.15 | 8.6 | N/A | |||
C++14 功能特性 | 提案 | 版本 | GCC | Clang | MSVC | EDG eccp | Intel C++ | IBM XLC++ | Sun/Oracle C++ | Embarcadero C++ Builder | Cray | Portland Group (PGI) |
C++11 功能特性
C++11 功能特性 | 提案 | 版本 | GCC | Clang | MSVC | EDG eccp | Intel C++ | IBM XLC++ | Sun/Oracle C++ | Embarcadero C++ Builder | Cray | Portland Group (PGI) | HP aCC | Digital Mars C++ | [折叠] |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
alignas | N2341 | c++11 | 4.8 | 3.0 | 19.0* | 4.8 | 15.0 | 13.1.2* | 5.13 | 是 | 8.6 | 2015 | |||
alignof | N2341 | c++11 | 4.5 | 2.9 | 19.0* | 4.8 | 15.0 | 13.1.2* | 5.13 | 是 | 8.4 | 2015 | |||
原子操作 | N2427 | c++11 | 4.4 | 3.1 | 17.0* | Yes | 13.0 | 13.1.2* | 5.14 | 是 | 8.4 | 2015 | |||
auto | N1984(v1.0) | c++11 | 4.4(v1.0) | 是 | 16.0* | 3.9 | 11.0(v0.9) 12.0(v1.0) | 11.1(v1.0) | 5.13 | 是 | 8.4 | 2015 | A.06.25 | ||
C99 预处理器 | N1653 | c++11 | 4.3 | 是 | 19.0* (部分:变参宏有漏洞) | 4.1 | 11.1 | 10.1 | 5.9 | 是 | 8.4 | 2015 | A.06.25 | 是 | |
constexpr | N2235 | c++11 | 4.6 | 3.1 | 19.0* (部分) | 4.6 | 13.0* 14.0 | 12.1* 13.1 | 5.13 | 是 | 8.4 | 2015 | A.06.28 | ||
decltype | v1.0: N2343v1.1: N3276 | c++11 | 4.3(v1.0) 4.8.1(v1.1) | 2.9 | 16.0* | 4.2(v1.0) 4.8(v1.1) | 11.0(v1.0) 12.0(v1.1) | 11.1(v1.0) | 5.13 | 是 | 8.4 | 2015 | A.06.25 | 8.52(v1.0) | |
预置和弃置的函数 | N2346 | c++11 | 4.4 | 3.0 | 18.0* | 4.1 | 12.0 | 13.1 | 5.13 | 是 | 8.4 | 2015 | A.06.25 | ||
委托构造函数 | N1986 | c++11 | 4.7 | 3.0 | 18.0* | 4.7 | 14.0 | 11.1 | 5.13 | 是 | 8.4 | 2015 | A.06.28 | ||
显式转换运算符 | N2437 | c++11 | 4.5 | 3.0 | 18.0* | 4.4 | 13.0 | 12.1 | 5.13 | 是 | 8.4 | 2015 | A.06.27 | ||
扩展的 friend 声明 | N1791 | c++11 | 4.7 | 2.9 | 16.0* (部分) 18.0* | 4.1 | 11.1* 12.0 | 11.1 | 5.13 | 是 | 8.4 | 2015 | A.06.25 | ||
extern template | N1987 | c++11 | 3.3 | 是 | 12.0* | 3.9 | 9.0 | 11.1 | 5.13 | 是 | 8.4 | 2015 | A.06.25 | ||
前置 enum 声明 | N2764 | c++11 | 4.6 | 3.1 | 17.0* | 4.5 | 11.1* 14.0 | 12.1 | 5.13 | 是 | 8.4 | 2015 | |||
继承的构造函数 | N2540 | c++11 | 4.8 | 3.3 | 19.0* | 4.8 | 15.0 | 13.1.1* | 5.13 | 是 | 8.4 | 2015 | |||
初始化器列表 | N2672 | c++11 | 4.4 | 3.1 | 18.0* | 4.5 | 13.0* 14.0 | 13.1.2* | 5.13 | 是 | 8.4 | 2015 | A.06.28 | ||
Lambda 表达式 | v0.9: N2550v1.0: N2658 v1.1: N2927 | c++11 | 4.5(v1.1) | 3.1 | 16.0(v1.0) 17.0(v1.1) | 4.1(v1.1) | 12.0(v1.1) | 13.1.2* | 5.13 | 是 | 8.4 | 2015 | A.06.25 | ||
局部及无名类型作为模板形参 | N2657 | c++11 | 4.5 | 2.9 | 16.0* | 4.2 | 12.0 | 13.1.2* | 5.13 | 是 | 8.4 | 2015 | A.06.27 | ||
long long | N1811 | c++11 | 是 | 是 | 14.0* | 是 | 是 | 是 | 是 | 是 | 8.4 | 2015 | 是 | 是 | |
内联命名空间 | N2535 | c++11 | 4.4 | 2.9 | 19.0* | 4.5 | 14.0 | 11.1 | 5.13 | 是 | 8.4 | 2015 | A.06.28 | ||
新字符类型 | N2249 | c++11 | 4.4 | 2.9 | 19.0* | 4.4 | 12.1* 14.0 | 13.1.1* | 5.13 | 是 | 8.4 | 2015 | A.06.27 | 8.52 | |
尾随的函数返回类型 | N2541 | c++11 | 4.4 | 2.9 | 16.0* | 4.1 | 12.0 | 12.1 | 5.13 | 是 | 8.4 | 2015 | A.06.27 | ||
nullptr | N2431 | c++11 | 4.6 | 2.9 | 16.0* | 4.2 | 12.1 | 13.1 | 5.13 | 是 | 8.4 | 2015 | A.06.27 | 8.52 | |
Unicode 字符串字面量 | N2442 | c++11 | 4.4 | 3.0 | 19.0* | 4.7 | 11.0* | 10.1* 13.1.1* | 5.7 | 是 | 8.4 | 2015 | A.06.28 | 8.52 | |
原始字符串字面量 | N2442 | c++11 | 4.5 | 是 | 18.0* | 4.7 | 14.0 | 13.1.1* | 5.13 | 是 | 8.4 | 2015 | A.06.28 | 8.52 | |
用户定义字面量 | N2765 | c++11 | 4.7 | 3.1 | 19.0* | 4.8 | 15.0 | 13.1.2* | 5.14 | 是 | 8.4 | 2015 | |||
右角括号 | N1757 | c++11 | 4.3 | 是 | 14.0* | 4.1 | 11.0 | 12.1 | 5.13 | 是 | 8.4 | 2015 | |||
右值引用 | v1.0: N2118v2.0: N2844 v2.1: N2844+ v3.0: N3053 | c++11 | 4.3(v1.0) 4.5(v2.1) 4.6(v3.0) | 是 | 16.0(v2.0) 17.0(v2.1) 19.0*(v3.0) | 4.5(v3.0) | 11.1(v1.0) 12.0(v2.0) 14.0(v3.0) | 12.1(v2.1) | 5.13 | 是 | 8.4 | 2015 | A.06.25 | ||
static_assert | N1720 | c++11 | 4.3 | 2.9 | 16.0* | 4.1 | 11.0 | 11.1 | 5.13 | 是 | 8.4 | 2015 | A.06.25 | 8.52 | |
强类型 enum | N2347 | c++11 | 4.4 | 2.9 | 17.0* | 4.0 | 13.0 | 12.1 | 5.13 | 是 | 8.4 | 2015 | A.06.25 | ||
模板别名 | N2258 | c++11 | 4.7 | 3.0 | 18.0* | 4.2 | 12.1 | 13.1.1* | 5.13 | 是 | 8.4 | 2015 | A.06.27 | ||
线程局域存储 | N2659 | c++11 | 4.4* 4.8 | 3.3* 3.3 | 16.0* (部分) 19.0* | 4.8 | 11.1* 15.0* | 10.1* 13.1.2* | 5.9* | 是 | 8.4 | 2015 | 8.52* | ||
无限制的联合体 | N2544 | c++11 | 4.6 | 3.0 | 19.0* | 4.6 | 14.0* | 13.1.2* | 5.13 | 是 | 8.4 | 2015 | A.06.28 | ||
类型特征 | N1836 | c++11 | 4.3 | 3.0 | 14.0* | 4.0 | 10.0 | 13.1.3 | 5.13 | 是 | 8.4 | 2015 | 6.16 | ||
变参模板 | v0.9: N2242v1.0: N2555 | c++11 | 4.3(v0.9) 4.4(v1.0) | 2.9(v1.0) | 18.0* | 4.3(v0.9) 4.3(v1.0) | 12.1(v1.0) | 11.1(v0.9) | 5.13 | 是 | 8.4 | 2015 | A.06.27 | ||
范围 for 循环 | N2930 | c++11 | 4.6 | 3.0 | 17.0* | 4.5 | 13.0 | 13.1.2* | 5.13 | 是 | 8.4 | 2015 | A.06.28 | ||
override 与 final | v0.8: N2928v0.9: N3206 v1.0: N3272 | c++11 | 4.7 | 2.9 | 14.0* (部分) 17.0* | 4.8(v1.0) | 12.0(v0.8) 14.0(v1.0) | 13.1.1* | 5.13 | 是 | 8.4 | 2015 | |||
属性 | N2761 | c++11 | 4.8 | 3.3 | 19.0* | 4.2 | 12.1 | 13.1.1* | 5.13 | 是 | 8.4 | 2015 | A.06.27 | ||
引用限定符 | N2439 | c++11 | 4.8.1 | 2.9 | 19.0* | 4.7 | 14.0 | 13.1.2* | 5.13 | 是 | 8.4 | 2015 | A.06.28 | ||
非静态数据成员初始化器 | N2756 | c++11 | 4.7 | 3.0 | 18.0* | 4.6 | 14.0 | 13.1.2* | 5.13 | 是 | 8.4 | 2015 | A.06.28 | ||
有并发的动态初始化及析构(魔法静态变量) | N2660 | c++11 | 4.3 | 2.9 | 19.0* | 是 | 11.1* | 13.1.2* | 5.13 | 是 | 8.4 | 2015 | A.06.25 | ||
noexcept | N3050 | c++11 | 4.6 | 3.0 | 19.0* | 4.5 | 14.0 | 13.1.1* | 5.13 | 是 | 8.4 | 2015 | A.06.28 | ||
垃圾收集与基于可达性的泄漏检测 | N2670 | c++11 | |||||||||||||
垃圾收集与基于可达性的泄漏检测(库支持) | N2670 | c++11 | 6 (无操作) | 3.4 (无操作) | 19.0* (无操作) | N/A | N/A | N/A | |||||||
金额、时间及十六进制浮点 I/O 操纵符 | 时间: N2071金额: N2072 | c++11 | 5 | 3.8 | 19.0* | N/A | N/A | 5.15 | N/A | ||||||
C++11 功能特性 | 提案 | 版本 | GCC | Clang | MSVC | EDG eccp | Intel C++ | IBM XLC++ | Sun/Oracle C++ | Embarcadero C++ Builder | Cray | Portland Group (PGI) | HP aCC | Digital Mars C++ |