- constexpr关键字
constexpr,从字面上看可以看出是用来声明常量表达式,但C++11不仅限于此。
constexpr同时可以声明常量函数和常量对象,这里的常量是指编译时期可以确定的常量。
普通的const关键字声明的函数在下面无效:
1 | const int getArraySize() { return 32; } |
使用constexpr重新定义:
1 | constexpr int getArraySize() { return 32; } |
也可以用常量构造函数来定义常量对象:
1 | class Rect |
可以这样声明constexpr对象
1 | constexpr Rect r(8,2); |
- 类型别名
C++11在typedef的基础上引入了一个新的类型别名机制,更容易理解。
1 | using MyInt = int; |
个人对这种方式也比较疑惑:将using 和 赋值符号放在一起,让人有些不知其所以然,不过从代码的角度来说还是比较好理解的。
同样可以用这个来声明函数指针类型,C++11之前的声明格式是
1 | typedef ReturnType (*FuncPointerName)( ArgType ); |
例如:
1 | typedef int (*FuncType)( char ); |
使用using声明格式是:
1 | using FuncPointerName = ReturnType (*) (ArgType); |
例如:
1 | using FuncType = int (*) (ArgType); |
这种方式相对于之前的MyInt声明更加直观。
对于成员函数指针来说可以像下面这样(多半用于模板类中的声明):
1 | using ClassMempFunc = ReturnType (ClassType::*) (ArgType); |
- 统一初始化
对于结构体和类,我们通常可以用下面的方式进行初始化:
1 | struct BasicStruct |
C++11之前对于结构体可以调用{…}进行初始化,然而对于类,需要用(…)调用构造函数。
C++11允许用{…}进行对象初始化:
1 | BasicClass myCalss = { 10, 15 }; // = 号也是可选的 |
这种统一初始化可以防止范围缩限(narrowing,又称窄化,我理解为数据截断),即当转换后的类型无法表示原类型时发出编译错误。
例如下面的函数调用:
1 | void Func( int i ) { ... } |
对于类来说可以在某些场合代替构造函数:
1 | BasicClass GetBasicClassObj( ) |
同样也适用于STL容器的初始化:
1 | std::vector<int> myVec = {10 , 20 , 30]; |
也可以用来初始化动态分配的数组:
1 | int *pArray = new int [4] { 0, 1, 2, 3}; |
最后,也可以用于构造函数的成员初始化列表:
1 | class MyClass |
- 空指针
C++11之前,用0来代表空指针,可以这么写:
1 | int* ptr = 0; |
但是这常常会和整数0混淆:
1 | void Func(char * pSrc) { ... } // 如果传入0作为空指针参数想调用这个函数, |
因此C++11 引入了空指针专用的名称nullptr,很多以往的C++代码要改咯。
- 尖括号
在C++11之前,有个众所周知的尖括号问题无法解决: 模板参数类型的模板。
必须手动在两个尖括号之前添加空格:
1 | vector<basic_string<wchart_t> > vec; // >>可能被作为流输出运算符 |
C++11已经可以识别这类的声明:
1 | vector<basic_string<wchart_t>> vec; // OK in C++11 |