1. C++语言历程
C++语言从1983年正式诞生以来,经历了多次的修订与改版,主要从包含两个大的节点,一是1998年,C++语言正式被C++标准委员会纳入标准,二是2011年,C++语言新增了许多新的特性,大大提升C++语言的实用性。可以把C++标准分成两个大的版本,C++1.0(C++98,C++03,C++03(tr1))和C++2.0(C++11,C++14,C++17,C++20(草案))
C++1.0和2.0的主要特性
C++版本 |
特性 |
C++98 |
主要集成在兼容C特性的基础上增加面向对象的特性,包括类、简单继承、内联机制、函数默认参数以及强类型检查,虚函数、函数重载、引用机制(符号为&)、const关键字以及双斜线的单行注释,多重继承、保护成员以及静态成员等特性,并集成了标准模板库STL |
C++03 |
主要修订C++98中存在的问题 |
C++03(tr1) |
发布C++希望引入新特性的报告,但没有完全引入,后期加入部分std::tr1相关的功能 |
C++11 |
新增正则表达式(正则表达式详情)、完备的随机数生成函数库、新的时间相关函数,原子操作支持、标准线程库(2011之前,C和C++语言均缺少对线程的支持)、一种能够和某些语言中foreach语句达到相同效果的新的for语法、auto关键字、新的容器类、更好的union支持、数组初始化列表的支持以及变参模板的支持等等新特性 |
C++14 |
主要对C++11变准文案描述进行了修正 |
C++17 |
简化C++语言的日常使用 |
C++20 |
– |
2. 各编译器对C++标准核心功能的支持
C++11核心功能 |
MSVC |
GCC |
ICC |
Clang |
替代方案 |
Rvalue references |
10.0 |
4.3 |
12.0 |
2.9 |
Boost.Move |
Rvalue references for *this |
Nov 13 |
4.8.1 |
14.0 |
2.9 |
|
Initialization of class objects by rvalues |
9.0 |
4.3 |
11.1 |
2.9 |
|
Non-static data member initializers |
12.0 |
4.7 |
14.0 |
3.0 |
|
Variadic templates |
Nov 12 |
4.3 |
12.1 |
2.9 |
|
Extending variadic template template parameters |
Nov 12 |
4.4 |
12.1 |
2.9 |
|
Initializer lists |
Nov 12 |
4.4 |
14.0 |
3.1 |
|
Static assertions |
10.0 |
4.3 |
11.1 |
2.9 |
Boost.StaticAssert |
auto-typed variables |
10.0 |
4.4 |
12.0 |
2.9 |
Boost.Typeof |
Multi-declarator auto |
10.0 |
4.4 |
12.0 |
2.9 |
Boost.Typeof |
Removal of auto as a storage-class specifier |
10.0 |
4.4 |
12.0 |
2.9 |
Boost.Typeof |
New function declarator syntax |
10.0 |
4.4 |
12.0 |
2.9 |
Boost.ReturnType |
New wording for C++11 lambdas |
10.0 |
4.5 |
12.0 |
3.1 |
Boost.Lambda |
Declared type of an expression |
10.0 |
4.3 |
12.0 |
2.9 |
Boost.Typeof |
Incomplete return types |
11.0 |
4.8.1 |
12.1 |
3.1 |
|
Right angle brackets |
9.0 |
4.3 |
11.1 |
2.9 |
TR1 |
Default template arguments for function templates |
Nov 12 |
4.3 |
12.1 |
2.9 |
|
Solving the SFINAE problem for expressions |
No |
4.4 |
12.1 |
2.9 |
|
Template aliases |
12.0 |
4.7 |
12.1 |
3.0 |
|
Extern templates |
9.0 |
4.3 |
11.1 |
2.9 |
|
Null pointer constant |
10.0 |
4.6 |
12.1 |
3.0 |
自己实现的null_ptr |
Strongly-typed enums |
11.0 |
4.4 |
14.0 |
2.9 |
#define |
Forward declarations for enums |
11.0 |
4.6 |
14.0 |
3.1 |
|
Generalized attributes |
14.0 |
4.8 |
12.1 |
3.3 |
|
Generalized constant expressions |
Nov 13 |
4.6 |
14.0 |
3.1 |
|
Alignment support |
Nov 13 |
4.8 |
No |
3.3 |
|
Delegating constructors |
Nov 12 |
4.7 |
14.0 |
3.0 |
|
Inheriting constructors |
Nov 13 |
4.8 |
15.0 |
3.3 |
|
Explicit conversion operators |
Nov 12 |
4.5 |
14.0 |
3.0 |
|
New character types |
14.0 |
4.4 |
14.0 |
2.9 |
|
Unicode string literals |
14.0 |
4.5 |
14.0 |
3.0 |
|
Raw string literals |
Nov 12 |
4.5 |
14.0 |
3.0 |
|
Universal character name literals |
14.0 |
4.5 |
12.1 |
3.1 |
|
User-defined literals |
VS14 CTP1 |
4.7 |
15.0 |
3.1 |
|
Standard Layout Types |
11.0 |
4.5 |
No |
3.0 |
|
Defaulted and deleted functions |
12.0 |
4.4 |
12.0 |
3.0 |
|
Extended friend declarations |
10.0 |
4.7 |
12.0 |
2.9 |
|
Extending sizeof |
Nov 13 |
4.4 |
14.0 |
3.1 |
|
Inline namespaces |
14.0 |
4.4 |
14.0 |
2.9 |
|
Unrestricted unions |
14.0 |
4.6 |
14.0 |
3.1 |
|
Local and unnamed types as template arguments |
9.0 |
4.5 |
12.0 |
2.9 |
|
Range-based for |
11.0 |
4.6 |
13.0 |
3.0 |
Boost.Foreach |
Explicit virtual overrides |
11.0 |
4.7 |
14.0 |
3.0 |
#define |
Minimal support for garbage collection and reachability-based leak detection |
10.0 |
No |
No |
No |
|
Allowing move constructors to throw [noexcept] |
Nov 13 |
4.6 |
14.0 |
3.0 |
|
Defining move special member functions |
14.0 |
4.6 |
14.0 |
3.0 |
|
Sequence points |
12.0 |
4.8 |
15.0 |
3.3 |
|
Atomic operations |
11.0 |
4.4 |
13.0 |
3.1 |
Boost.Atomic |
Strong Compare and Exchange |
11.0 |
4.8 |
13.0 |
3.1 |
Boost.Atomic |
Bidirectional Fences |
11.0 |
4.8 |
13.0 |
3.1 |
Boost.Atomic |
Memory model |
12.0 |
4.8 |
No |
3.2 |
Boost.Atomic |
Data-dependency ordering: atomics and memory model |
11.0 |
4.8 |
No |
3.2 |
Boost.Atomic |
Propagating exceptions |
10.0 |
4.4 |
12.0 |
2.9 |
Boost.Exception |
Abandoning a process and at_quick_exit |
14.0 |
4.8 |
No |
No |
|
Allow atomics use in signal handlers |
12.0 |
4.8 |
No |
3.1 |
|
Thread-local storage |
14.0 |
4.8 |
No |
3.3 |
Boost.Thread |
Dynamic initialization and destruction with concurrency |
Nov 13 |
4.8 |
No |
2.9 |
|
func predefined identifier |
Nov 13 |
4.3 |
11.1 |
2.9 |
FUNCTION |
C99 preprocessor |
No |
4.3 |
11.1 |
2.9 |
|
long long |
9.0 |
4.3 |
11.1 |
2.9 |
__int64 |
Extended integral types |
No |
No |
No |
No |
|
C++14核心功能 |
MSVC |
GCC |
ICC |
Clang |
替代方案 |
Tweak to certain C++ contextual conversions |
12.0 |
4.9 |
16.0 |
3.4 |
|
Binary literals |
14.0 |
4.9 |
11.0 |
2.9 |
|
Return type deduction for normal functions |
Nov 13 |
4.9 |
15.0 |
3.3 |
|
Generalized lambda capture (init-capture) |
14.0 |
4.9 |
15.0 |
3.4 |
|
Generic (polymorphic) lambda expressions |
Nov 13 |
4.9 |
16.0 |
3.4 |
|
Variable templates |
15.0 |
5.0 |
No |
3.4 |
|
Relaxing requirements on constexpr functions |
15.0 |
5.0 |
No |
3.4 |
|
Member initializers and aggregates |
15.0 |
5.0 |
16.0 |
3.3 |
|
Clarifying memory allocation |
No |
No |
No |
3.4 |
|
Sized deallocation |
14.0 |
5.0 |
17.0 |
3.4 |
|
[[deprecated]] attribute |
14.0 |
4.9 |
16.0 |
3.4 |
|
Single-quotation-mark as a digit separator |
14.0 |
4.9 |
16.0 |
3.4 |
|
C++17核心功能 |
MSVC |
GCC |
ICC |
Clang |
替代方案 |
static_assert with no message |
15.0 |
6 |
No |
3.5 |
C++11’s static_assert |
Disabling trigraph expansion by default |
12.0 |
5.1 |
No |
3.5 |
|
typename in a template template parameter |
14.0 |
5 |
17.0 |
3.5 |
|
New auto rules for direct-list-initialization |
14.0 |
5 |
17.0 |
3.8 |
|
Fold expressions |
No |
6 |
No |
3.6 |
|
Attributes for namespaces and enumerators |
14.0 |
6 |
No |
3.6 |
|
u8 character literals |
14.0 |
6 |
17.0 |
3.6 |
|
Nested namespace definition |
15.0 |
6 |
17.0 |
3.6 |
|
Allow constant evaluation for all non-type template arguments |
No |
6 |
No |
3.6 |
|
Remove deprecated register storage class |
No |
7 |
No |
3.8 |
|
Remove deprecated bool increment |
No |
7 |
No |
3.8 |
|
Make exception specifications part of the type system |
No |
7 |
No |
No |
|
__has_include in preprocessor conditionals |
No |
5 |
No |
Yes |
|
New specification for inheriting constructors (DR1941 et al) |
No |
7 |
No |
3.9 |
|
[[fallthrough]] attribute |
15.0 |
7 |
No |
3.9 |
|
[[nodiscard]] attribute |
No |
7 |
No |
3.9 |
|
[[maybe_unused]] attribute |
No |
7 |
No |
3.9 |
|
Aggregate initialization of classes with base classes |
No |
7 |
No |
3.9 |
|
constexpr lambda expressions |
No |
7 |
No |
No |
|
Unary Folds and Empty Parameter Packs |
No |
6 |
No |
3.9 |
|
Differing begin and end types in range-based for |
15.0 |
6 |
No |
3.9 |
|
Lambda capture of *this |
No |
7 |
No |
3.9 |
|
Direct-list-initialization of enums |
No |
7 |
No |
3.9 |
|
Hexadecimal floating-point literals |
No |
3.0 |
No |
Yes |
|
Using attribute namespaces without repetition |
No |
7 |
No |
3.9 |
|
Dynamic memory allocation for over-aligned data |
No |
7 |
No |
No |
|
Template argument deduction for class templates |
No |
7 |
No |
No |
|
Non-type template parameters with auto type |
No |
7 |
No |
No |
|
Guaranteed copy elision |
No |
7 |
No |
No |
|
Stricter expression evaluation order |
No |
7 |
No |
No |
|
Requirement to ignore unknown attributes |
No |
Yes |
No |
Yes |
|
constexpr if-statements |
No |
7 |
No |
3.9 |
|
Inline variables |
No |
7 |
No |
3.9 |
|
Structured bindings |
No |
7 |
No |
No |
|
Separate variable and condition for if and switch |
No |
7 |
No |
3.9 |
|
Matching template template parameters to compatible arguments |
No |
7 |
No |
No |
|
Removing deprecated dynamic exception specifications |
No |
7 |
No |
No |
|
Pack expansions in using-declarations |
No |
No |
No |
No |
|
3. c++11核心功能
3.1 可变参数模板(Variadic Template)
- 主要增加关键字…, 表示一个组或者包,代表可变的参数个数或类型
- 从模板函数上来看,可以更好的完成递归函数的调用,具体如代码example1
- 从类模板的角度看,可以更方便的完成递归继承,具体如代码example2
example1 函数模板
//注意必须配一个无参的print函数,否则递归没有边界
void print()
{
}
//定义一个模板函数 1 + n, 更具化,
//(1)... 表示一个所谓的包(pack),一组
//(2)typename... Types 模板参数包
//(3)const Types&... args 函数参数类型包
//(4)args... 参数包
template
void print(const T& firstArg, const Types&... args)
{
std::cout<<"i'm 1+n"<
void print(const Types&... args)
{
std::cout<<"i'm n"<
example2 类模板
//注意,一定要先加这一句
template class MytestClassTem;
template<> class MytestClassTem<>{};
template
class MytestClassTem
: private MytestClassTem
{
typedef MytestClassTem inherited;
public:
MytestClassTem(){}
MytestClassTem(First v, others... args)
:m_first(v), inherited(args...){}
First first(){return m_first;}
//此处返回的是父类的实例
inherited& other(){return *this;}
protected:
First m_first;
};
/////调用
MytestClassTem obj(41, 6.3, "hello");
std::cout<<"子级:"<
3.2 右尖括号(Right Angle Brackets)
#include
typedef std::vector > Table; // OK
typedef std::vector> Flags; // Error
#include
typedef std::vector > Table; // OK
typedef std::vector> Flags; // OK
3.3 空指针(nullptr)
- C++11之前没有关键字nullptr(其对应的类型为std::nullptr_t)
- nullptr用于替换0或者NULL,因为NULL本身是定义为0的,有时候使用会产生歧义
fun(0);//call fun(int)
int i = NULL;
fun(i);//call fun(int)
char* pp = NULL;
fun(pp);//call fun(void*)
fun(NULL);//有歧义
fun(nullptr);//call fun(void*)
3.4 auto关键字
- 在C++11中,可以auto定义变量,而不指定变量的类型
- 编译器会从等号右边的表达式或变量来推断auto变量的类型
- auto 一般用于替代变量类型名字太长,或表达式类型太复杂的场景
//简单类型不建议使用auto
auto data = 2;
//typeid包含在#include
std::cout< vecStr;
auto itr = vecStr.begin(); //auto取代 std::vector::iterator itr = vecStr.begin()
auto lam = [](int x)->bool{return x = 0;}; // auto取代lambda表达式的类型
3.5 统一初始化(Uniform Initialization)
- C++11之前,有三种为变量或对象初始化的方式,大括号,小括号, 赋值符号
- C++ 11 引入统一的初始化方式 ————统一使用大括号,内部编译器会进行转换,编译器会在识别到{t1,t2,…,tn}时,自动保存至一个initializer_list对象中,并关联至一个一个array,在调用构造函数时,会将array中的元素逐一分解传递给构造函数
- 若构造函数的入参为initializer_list时,则不做分解,直接整包传进去
class TestInitializerList
{
public:
TestInitializerList(int a, int b)
{
std::cout<<"TestInitializerList(int,int), a = "< initList)
{
std::cout<<"TestInitializerList(initializer_list initList) ,vals = ";
for(auto i : initList)
{
std::cout<的构造函数存在,则调用,如不存在,则逐一分解,调用构造函数TestInitializerList(int a, int b)
TestInitializerList c{34,56,78};////若包含std::initializer_list的构造函数存在,则调用,则分解,分解后若有匹配的构造函数则调用,没有匹配的会报错
TestInitializerList d={67,90};//同d{65,9};
- C++11也兼容之前的小括号和赋值符号的初始化方式
////////before C++11
//小括号
Rect r(3,4);
r.printRect();
//大括号
int ia[2] = {3,4};
//赋值符号
Rect r1 = {4,5};//在C++11之前只能使用构造函数来对对象初始化
r1.printRect();
//C++11 Uniform Initializzation
int ib[2]{6,7};
std::vector vec{8,9};
Rect r2{3,9};
r2.printRect();
- C++11引入统一的初始化对象或变量的方式,其主要目的是构造对象时可接收可变的参数,在标准库的设计上提供了很大的便利.
- 引入了std::initializer_list<>模板类,其内部维护了一个std::array数据
//有了Initializer List后,直接不限个数,#include
std::cout<
std::cout<
int i;//i有一个未定义的值
std::cout<
3.6 关键字explicit
- explicit含义是明确的,显示的,一般用在构造函数前面,但在C++11之前,只能放在包含一个入参的构造函数前面
struct TestExplicit
{
explicit TestExplicit(int re, int im = 0):real(re),imag(im)
{}
TestExplicit operator+(const TestExplicit& x)
{
return TestExplicit((real+x.real),(imag+x.imag));
}
int real;
int imag;
};
TestExplicit a(12,5);
std::cout<
- C++11中允许explicit放在包含多个入参的构造函数前面(其实是基于Uniform Initialization,扩展了其功能)
class TestNewExplicit
{
public:
TestNewExplicit(int a,int b)
{
std::cout<<"TestNewExplicit(int a,int b), a = "< initList)
{
std::cout<<"TestNewExplicit(std::initializer_list initList) ,vals = ";
for(auto i : initList)
{
std::cout<参数的构造函数,则需要编译器自动分解,匹配个数进行调用相应参数的构造函数
//若分解匹配后的构造函数前面加了explicit,则不能直接调用
//converting to 'TestNewExplicit' from initializer list to TestNewExplicit
TestNewExplicit p4 = {1,2,3};
3.7 基于范围的for循环(range-based for statement)
- 从容器中依次取出元素进行处理
- 接收者为引用时,则用一个指针指向容器中的元素,不需要拷贝一份
for(int i : {1,2,3,4})
{
std::cout< vec{4,5,6};
for(auto& j : vec)
{
std::cout<
3.8 =default/=delete
- Big-Three:表示类中默认的析构函数,拷贝构造函数,operator=(C++11中引入右值引用后,增加了移动拷贝构造函数,移动operator=, 被称为Big-Five),这些函数不能被重载
- =default ,只能被用在Big-Five函数后面,表示使用编译器默认的函数
- =delete, 一般用在Big-Five函数后面,但也可以使用在其他普通函数函数后面,表示告知编译器不要定义该函数(建议不要用在析构函数上)
class Test
{
public:
//不能使用编译器默认的构造函数
Test() = delete;
Test(int a)
{
std::cout<<"Test(int a)"<
附:经典网站及书籍
名称 |
说明 |
C++14标准PDF |
https://doc.imzlp.me/viewer.html?file=docs/standard/isocpp2014.pdf |
C++11标准PDF |
https://doc.imzlp.me/viewer.html?file=docs/standard/isoc11.pdf |
多种编译器对C++11的支持 |
http://www.klayge.org/wiki/index.php/多种编译器对C%2B%2B11的支持 |
多种编译器对C++14的支持 |
http://www.klayge.org/wiki/index.php/多种编译器对C%2B%2B14的支持 |
多种编译器对C++17的支持 |
http://www.klayge.org/wiki/index.php/多种编译器对C%2B%2B17的支持 |
在线开发环境 |
https://wandbox.org/ |
各VS版本对C++11功能的支持 |
https://blog.csdn.net/xiaomu_347/article/details/82563688 |
侯捷老师的《C++11新特性》视频 |
https://www.bilibili.com/video/av51863195/?p=9 |