空指针
nullptr 空指针的字面值常量,它的类型是std::nullptr_t(定义位于cstddef)
自动类型推断
auto关键字,由auto定义的变量必须初始化。
统一初始化和初始化列表
C++11 introduced the concept of uniform initialization, which means that for any initialization, you can use one common syntax. This syntax uses braces, so the following is possible now:
int values[] { 1, 2, 3 };
std::vectorv { 2, 3, 5, 7, 11, 13, 17 };
std::vectorcities {"Berlin", "New York", "London", "Braunschweig", "Cairo", "Cologne"};
std::complexc{4.0,3.0}; // equivalent to c(4.0,3.0)
使用初始化列表初始化时,不提供初始值时默认值初始化(0或nullptr),其他初始化方式若为提供初始值则值是未定义的。
int i; // i has undefined value
int j{}; // j is initialized by 0
int* p; // p has undefined value
int* q{}; // q is initialized by nullptr
使用初始化列表初始化时,若提供的值会将会损失精度时,编译器报错。
int x1(5.3); // OK, but OUCH: x1 becomes 5
int x2 = 5.3; // OK, but OUCH: x2 becomes 5
int x3{5.0}; // ERROR: narrowing
int x4 = {5.3}; // ERROR: narrowing
char c1{7}; // OK: even though 7 is an int, this is not narrowing
char c2{99999}; // ERROR: narrowing (if 99999 doesn’t fit into a char)
std::vector<int>v1 { 1, 2, 4, 5 }; // OK
std::vector<int>v2 { 1, 2.3, 4, 5.6 }; // ERROR: narrowing doubles to ints
std::initializer_list<>使得函数支持传入多值(通过初始值列表)
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}); // pass a list of values to print()
基于范围的循环表达式
for ( decl : coll ) {
statement
}
coll必须是支持迭代器的容器,或者是数组,或者是值列表类型
移动语义和右值引用
避免无意义的拷贝和暂存变量。
The programmer, however, has to specify that a move is possible unless a temporary is used.
std::move(),位于<utility> 。std::move(x)本身不会进行移动操作,只是将临时变量转换为一个右值引用(X &&x,使用双&声明,表明右值是可以修改的),表明此临时变量x将不会再使用了,可以将它的内容据为己有(不需要拷贝)。
移动之后不再使用原来的变量,原来的变量有效但是状态未定义。
void foo(X &x);//只接受左值
void foo(const X &x);//接受左值和右值
void foo(X &&x);//接受右值
原始字符串字面值、被编码的字符串字面值
Raw String Literals
此类型的字符串可包含特殊字符,语法R"delim(...)delim",delim是16个基本字符组成的分隔符除了反斜杠,空格,圆括号;
例如:R"(\\n)"对应的普通字符串是"\\\n"
常用来定义正则表达式。
Encoded String Literals
使用编码前缀,定义特殊编码的字符串常量:
u8:utf-8,const char
u:char16_t
U:char32_t
L:wchar_t
关键字noexcept
声明一个函数不能或不准备抛出异常。
void foo() noexcept;
若在foo函数内部没有处理发生的异常,程序会终止,调用std::terminate(),它默认调用std::abort();
关键字constexpr
使得表达式在编译期间判断是否是常量,或者修饰返回值返回一个常量。
constexpr int square (int x){
return x * x;
}
float a[square(9)]; // OK since C++11: a has 81 elements
模板特性
Variadic Templates
可变模板参数个数,例如处理不同类型的参数
void print (){}
template<typename T, typename... Types>
void print (const T& firstArg, const Types&... args)
{
std::cout << firstArg << std::endl; // print first argument
print(args...); // call print() for remaining arguments
}
Alias Templates (Template Typedef)
template<typename T>
using Vec = std::vector>; // standard vector using own allocator
Vec coll;//即std::vector<int, MyAlloc<int>> coll;
lambda表达式
基本语法:
[ capture list ] { function body } 或
[ capture list ] ( paramters list ) mutable throwSpec -> retType { function body }
mutable、 throwSpec、 -> retType 可选
调用:直接调用、生成lambda变量间接调用
[ ] { std::cout << "hello lambda" << std::endl; } (); 或
auto func = [ ] (const std::string &s){ std::cout << "hello lambda" <<s << std::endl; };
func("good");
使用尾置返回:
未指明返回值类型时,若只有一个return语句,根据返回值自行推断;若有其他语句则返回void。
捕获规则:全局变量不用捕获即可使用
[ ]:不捕获任何变量
[=]:值捕获本作用域外变量
[&]:引用捕获作用域外变量
[x, &y]:显式值捕获x,引用捕获y
[=, &y]:值捕获除y的所有变量,y为引用捕获
[&, x]:引用捕获除x的所有变量,x为值捕获
值捕获变量在定义lambda时就已经确定,在内部不可更改其值,但使用mutable说明符可以使之改变。
lambda的类型
lambda的类型是匿名函数,每个不同的lambda的类型是不一样的。
#include<functional>
例如表达式
[ ] (int a, int b) -> int { return a + b; }
的类型是std::function<int(int ,int)>,用作返回值类型,可以返回一个lambda对象
std::function<int(int, int)>returnLambda () {
return [] (int x, int y) { return x*y; };
}
auto f = returnLambda();
cout <<f(1,2)<<endl;
关键字decltype
编译器推断表达式的类型:用于声明返回值类型,元编程或传递lambda的类型
std::map<std::string, sloat> coll;
decltype(coll)::value_type elem;
新的函数声明语法
template<typename T1, typename T2>
auto add(T1 x, T2 y) -> decltype(x+y);//尾置返回,确定返回类型必须预先知道x,y的类型,但返回类型推断放在函数名前面无效(x,y类型此时未知)
作用域枚举(强枚举,枚举类)
enum class Salutation : char { mr, ms, co, none };
1,不可隐式的转换到int或从int转换
2,使用作用域运算符引用Salutation::mr;
3,可以显式定义类型(:char),否则默认是:int
4,可前向声明枚举类型
新的基本数据类型
char16_t, char32_t, long long, unsigned long long ,std::nullptr_t
其他新特性
Nontype Template Parameters
bitset<32> flags32; // bitset with 32 bits
bitset<50> flags50; // bitset with 50 bits
Default Template Parameters
template<typename T, typename container = vector<T>>
class MyClass;
MyClass<int> x1;//即MyClass<int, vector<int>>
Keyword typename
用来说明其修饰的东西是类型
Member Templates
类的成员函数可以为模板
Nested Class Templates
嵌套类也可以为类模板
显式初始化基本数据类型
使用不带参数的显式构造初始化基本数据类型时,为0初始化(所有值都为0)
int i1; // undefined value
int i2 = int(); // initialized with zero
int i3{}; // initialized with zero (since C++11)
main函数的定义
1,
int main{}
2,
int main (int argc, char* argv[]){}
不一定要return 语句,隐式返回0,表示成功执行;返回非0则表示出错;
不使用return来结束程序可使用exit(), quick_exit(), terminate();