再谈C++11新特性

52 阅读3分钟

线程局部存储

C++11定义了thread_local关键字来定义线程局部存储变量,这样的变量生命期是线程启动到线程结束,除了本线程外,没有其他线程可以访问到这样的变量。

C++11仅规定了线程局部存储的行为,而没有规定其具体实现,不同的编译器在不同的环境中可能会有不同的实现方式。

快速退出:quick_exit, at_quick_exit

在过去,大体上有三种退出程序的方式:terminate(), abort(), exit()。

  • terminate是有未处理的异常时会被调用的方法,可以使用set_terminate方法更改默认行为,terminate默认调用abort;
  • abort是进程不得不终止时,被调用的函数,它会向本进程发送一个SIGABRT信号,该信号默认会导致操作系统直接释放该进程的所有资源并终止进程;
  • exit是进程自发调用的退出函数,它代表着进程运行到了某个节点,该退出了,它会导致每一个自动变量的析构函数被调用(是的,仅自动变量,也就是栈变量会被调用析构函数,至于单例什么的需要自己处理),并调用at_exit注册的函数,然后才会回收进程;

C++11新增了quick_exit标准方法,该方法语意上和exit一样,都是程序自发终止,但和exit不同的是,它不会进行本进程的清理工作,在多线程环境下也不会先等待线程结束,而是直接让操作系统终止进程并回收资源。

为改变思想方式而改变

指针空值-nullptr

C++11定义了nullptr_t和nullptr,前者是类型,后者是该类型的值。

nullptr可以隐式转换为任何指针,但无法被隐式转换为bool类型,无法使用if (nullptr)这样的表达式;此外它所属的nullptr_t是一个基础类型,nullptr无法被推导为T*这样的模板参数。

默认函数的控制

C++11规定可以使用 = default 来使编译器生成默认版本的成员函数,可以由编译器生成的函数包括:

  • 空构造函数
  • 拷贝构造函数
  • 拷贝赋值函数
  • 移动构造函数
  • 移动拷贝函数
  • 析构函数

此外,编译器还为所有自定义类型提供以下全局默认操作符函数:

  • operator,
  • operator&
  • operator&&
  • operator*
  • operator->
  • operator->*
  • operator new
  • operator delete

lambda函数

lambda语法:

[<捕获外部变量>]<(可选)mutable>(<(可选)参数列表>) -> <(可选)返回值> {<函数体>}

  • 捕获外部变量:变量需要用&或者=开头来引用,直接写&或者=后面不跟变量表示捕获所有外部变量,=表示按值捕获,&表示引用捕获;
  • mutable:labmda默认是内联的const函数,不可以修改任何捕获的外部的按值捕获的变量(因为目前lambda的语意其实和仿函数完全一致,在仿函数中,所有捕获的外部变量都是仿函数类的成员,因此const函数不可以修改类成员,到lambda这里变成了lambda不可以修改捕获变量),但是引用捕获的变量则可以修改(这个行为也是和仿函数一致的,const函数内可以调用任意成员引用的方法,修改其属性,因为将引用声明成const,和将指针声明成const类似,都仅仅是禁止修改引用本身,但并没有限制对引用或者指针指向的变量进行修改)。如果希望lambda不是一个const函数,就要添加mutable声明;
  • 参数列表:
  • 返回值:当能够从函数体中推测出明确的返回值类型时,可以忽略;
  • 函数体: