C++11有那些新特性

C++11最常用的新特性如下:
auto关键字:编译器可以根据初始值自动推导出类型。但是不能用于函数传参以及数组类型的推导
nullptr关键字: nullptr是一种特殊类型的字面值,它可以被转换成任意其它的指针类型;而NULL一般被宏定义为0,在遇到重载时可能会出现问题。
智能指针: C++11 新增了std: :sharedptr、std::weak ptr 等类型的智能指针,用于解决内存管理的问题。
初始化列表:使用初始化列表来对类进行初始化
右值引用:基于右值引用可以实现移动语义和完美转发,消除两个对象交互时不必要的对象拷贝,节省运算存储资源,提高效率
atomic原子操作用于多线程资源互斥操作
新增STL容器array以及tuple

  1. 关键字及新语法
    1. auto关键字及用法
    2. nullptr 关键字及用法
    3. for循环语法
  2. STL容器
    1. std: :array
    2. std: :forward_ _list
    3. std: :unordered_ map
    4. std: :unordered_ set
  3. 多线程
    1. std: :thread
    2. st: :atomic
    3. std: :condition_ variable
  4. 智能指针内存管理
    1. std: :shared_ ptr
    2. std: :weak_ ptr
  5. 其他
    1. std: :function、 std: :bind封装可执行对象
    2. lamda表达式

      C++11中的可变参数模板、右值引用和lambda新特性

可变参数模板

C++11的可变参数模板,对参数进行了高度泛化,可以表示任意数目、任意类型的参数,其语法为:在class或typename后面带上省略号。
例如:

  1. Template<class ... T>
  2. void func(T ... args){
  3. cout<<”num is”<<sizeof ... (args) <<endl;
  4. }
  5. func();//args不含任何参数
  6. func(1) ;//args包含一个int类型的实参
  7. func(1, 2.0)//args包含-一个 int一个double类型的实参

其中T叫做模板参数包,args叫做函数参数包
省略号作用如下:

  1. 声明一个包含0到任意个模板参数的参数包
  2. 在模板定义得右边,可以将参数包展成一个个独立的参数

C++11可以使用递归函数的方式展开参数包,获得可变参数的每个值。通过递归函数展开参数包,需要提供一个参数包展开的函数和-个递归终止函数。例如:

  1. #include using namespace std;
  2. //最终递归函数
  3. void print (){
  4. cout <<" empty" << endl;
  5. }
  6. //展开函数
  7. template void print(T head, Args... args) {
  8. cout << head << ","; print (args...);
  9. }
  10. int main(){
  11. print(1234);
  12. return 0;
  13. }

参数包Args …在展开的过程中递归调用自己,没调用一次参数包中的参数就会少一个,直到所有参数都展开为止。当没有参数时就会调用非模板函数printf终止递归过程。

右值引用

C++中,左值通常指可以取地址,有名字的值就是左值,而不能取地址,没有名字的就是右值。而在指C++11中,右值是由两个概念构成,将亡值和纯右值。纯右值是用于识别临时变量和一些不跟对象关联的值,比如1+3产生的临时变量值,true等,而将亡值通常是指具有转移语义的对象,比如返回右值引用T&&的函数返回值等。
C++11中,右值引用就是对一个右值进行引用的类型。由于右值通常不具有名字,所以我们般只能通过右值表达式获得其引用,比如:

  1. T & a=ReturnRvale() ;

假设ReturnRvalue()函数返回-一个右值,那么上述语句声明了一个名为a的右值引用,其值等于ReturnRvalue函数返回的临时变量的值。基于右值引用可以实现转移语义和完美转发新特性。

  1. 移动语义

对于一个包含指针成员变量的类,由于编译器默认的拷贝构造函数都是浅拷贝,所有我们一般需要通过实现深拷贝的拷贝构造函数,为指针成员分配新的内存并进行内容拷贝,从而避免悬挂指针的问题。

  1. 完美转发

完美转发是指在函数模板中,完全依照模板的参数的类型,将参数传递给函数模板中调用的另一个函数,即传入转发函数的是左值对象,目标函数就能获得左值对象,转发函数是右值对象,目标函数就能获得右值对象,而不产生额外的开销。
因此转发函数和目标函数参数一般采用引用类型,从而避免拷贝的开销。其次,由于目标函数可能需要能够既接受左值引用,又接受右值引用,所以考虑转发也需要兼容这两种类型。

Lambda表达式

Lambda表达式定义-一个匿名函数,并且可以捕获一定范围内的变量,其定义如下:

  1. [capture] (params) mutable- >return-type {statement}

其中,[capture]:捕获列表,捕获上下文变量以供lambda使用。同时[]是lambda寅初复,编译器根据该符号来判断接下来代码是否是lambda函数。
(Params):参数列表,与普通函数的参数列表一致, 如果不需要传递参数,则可以连通括号一起省略。
mutable是修饰符,默认情况下lambda函数总是一个const函数,Mutable可以取消其常量性。在使用该修饰符时,参数列表不可省略。
->return-type:返回类型是返回值类型
{statement} :函数体,内容与普通函数一样,除了可以使用参数之外,还可以使用所捕获的变量。
Lambda表达式与普通函数最大的区别就是其可以通过捕获列表访问一些上下文中的数据。
其形式如下:
口[var]表示值传递方式捕捉变量var。
口[=]表示值传递方式捕捉所有父作用城的变量(包括this )。
口[&var]表示引用传递捕捉变量var。
口[&]表示引用传递捕捉所有父作用域的变量(包括this )。
口[this]表示值传递方式捕捉当前的this指针。
Lambda的类型被定义为“闭包”的类,其通常用于STL库中,在某些场景下可用于简化仿函数的使用,同时Lambda作为局部函数,也会提高复杂代码的开发加速,轻松在函数内重用代码,无须费心设计接口。