1.模板表达式中的空格可以被省略
vector<list<int> >; // 每个C++版本都可以
vector<list<int>>; // 从C++11开始就可以
2.空指针
C++11中提供了一种专门的空指针类型std::nullptr_t,你可以用nullptr来代替以前的NULL引起的一些问题:
void f(int);
void f(void*);
f(0); // 调用f(int)
f(NULL); // 如果NULL是0就调用f(int)
f(nullptr); // 调用f(void*)
3.自动类型转换
auto i = 42; // i 的类型是 int
double f();
auto d = f(); // d 的类型是 double
4.统一初始化列表
C++11中支持大括号来进行初始化:
int values[] { 1, 2, 3 };
std::vector<int> v { 2, 3, 5, 7, 11, 13, 17 };
std::vector<std::string> cities {
"Berlin", "New York", "London", "Braunschweig", "Cairo", "Cologne"
};
std::complex<double> c{4.0,3.0}; // 等价于c(4.0,3.0)
并且使用{}初始化会自动赋予初始化值
int i; // i 未定义值
int j{}; // j 初始化为0
int* p; // p 未定义值
int* q{}; // q 初始化为nullptr
注意的是,使用{}初始化列表会禁止收窄(narrowing)转换。
int x1(5.3); // 允许, 但是x1会赋值为5
int x2 = 5.3; // 允许, 但是x2会赋值为5
int x3{5.0}; // 错误: 收窄转换
int x4 = {5.3}; // 错误: 收窄转换
char c1{7}; // 允许:即使7是int,但不属于收窄转换
char c2{99999}; // 错误:收窄转换
std::vector<int> v1 { 1, 2, 4, 5 }; // 允许
std::vector<int> v2 { 1, 2.3, 4, 5.6 }; // 错误:double收窄为int
5.可变形参
void print (std::initializer_list<int> vals)
{
for (auto p=vals.begin(); p!=vals.end(); ++p) { // 处理一系列值
std::cout << *p << "\n";
}
}
print ({12,3,5,7,11,13,17}); //利用初始化列表传递一系列值给实参
可以用explict关键字给它限制:
class P
{
public:
P(int a, int b) {
...
}
explicit P(int a, int b, int c) {
...
}
};
P x(77,5); // 允许
P y{77,5}; // 允许
P z {77,5,42}; // 允许
P v = {77,5}; // 允许 (隐式转换是允许的)
P w = {77,5,42}; // 必须显式转换
6.foreach循环
std::vector<double> vec;
...
for ( auto& elem : vec ) {
elem *= 3;
}
注意该循环过程中的elem赋值会调用拷贝构造函数,为了避免无谓的开销,尽量使用const引用。
待续。。。