本文已参与「新人创造礼」活动,一起开启掘金创造之路

C++11新特性

C++学习:6、C++ 11新特性;C++ 14;C++ 异常;智能指针


怎么查看咱们现在运用的是什么 C++ 规范

C++学习:6、C++ 11新特性;C++ 14;C++ 异常;智能指针


1、auto

  • 能够从初始化表达式中推断出变量的类型,大大简化编程作业
  • 归于编译器特性不影响最终的机器码质量不影响运转效率

C++学习:6、C++ 11新特性;C++ 14;C++ 异常;智能指针


2、decltype

  • 能够获取变量的类型

C++学习:6、C++ 11新特性;C++ 14;C++ 异常;智能指针


3、nullptr(null pointer:空指针)

  • 能够解决NULL的二义性问题

C++学习:6、C++ 11新特性;C++ 14;C++ 异常;智能指针

在 C++ 11 之前,NULL 既能代表指针、也能够代表整数 0 这样写代码会报错、

所以在 C++ 11 之后,咱们运用 nullptr 来特指指针NULL 为整数 0.


4、快速遍历:

之前的数组遍历:

int array[] = {0,1,2,3,4,5};
int i = 0;
for(i=0;i<sizeof(array); i++){
    cout<< array[i] << endl;
}

C++ 11 之后的遍历:

  • 咱们不需求理睬数组的大小,编译器会挨个将元素赋值给 item 元素
int array[] = {0,1,2,3,4,5};
for(int item = array){     
    cout<< item << endl;
}

5、lambda表达式

lambda 表达式的结构很复杂,有很多种方式,它的本质便是一个函数

创造它的意图:为了将函数的效果域,放到函数体里边

(1)最简略的方式:[capture list] {function body} ,了解:

  • 这个是一个特别的表达式,里边包括 捕获列表 + 函数实体
  • 它的本质便是一个函数

C++学习:6、C++ 11新特性;C++ 14;C++ 异常;智能指针

接下来给 lambda 表达式进行赋值

  • 函数实体既没有返回值,也没有函数实体。
  • 运用函数指针指向它。

C++学习:6、C++ 11新特性;C++ 14;C++ 异常;智能指针

更为简洁的赋值

C++学习:6、C++ 11新特性;C++ 14;C++ 异常;智能指针

调用 lambda 函数实体

C++学习:6、C++ 11新特性;C++ 14;C++ 异常;智能指针


(2)添加函数的参数列表:[capture list] (params list) {function body}

  • 中心添加了参数列表,这个函数的参数列表

C++学习:6、C++ 11新特性;C++ 14;C++ 异常;智能指针


(3)添加函数的返回值:[capture list] (params list) -> return type {function body}

  • -> return type ,return type 为这个函数的返回值类型
  • 可是 -> return type 能够进行省掉。

C++学习:6、C++ 11新特性;C++ 14;C++ 异常;智能指针


6、lambda 捕获变量

描绘:

C++学习:6、C++ 11新特性;C++ 14;C++ 异常;智能指针

解决

C++学习:6、C++ 11新特性;C++ 14;C++ 异常;智能指针

也能够进行隐式捕获:(并且默认是 值捕获

C++学习:6、C++ 11新特性;C++ 14;C++ 异常;智能指针


留意点:

(1)默认都是 值捕获

C++学习:6、C++ 11新特性;C++ 14;C++ 异常;智能指针

(2)地址捕获 :将 a 的地址传递进来。

C++学习:6、C++ 11新特性;C++ 14;C++ 异常;智能指针


7、Lambda表达式 – mutable

问题描绘:假如咱们想在 lambda 表达式傍边修正传进行来的变量值

(1)运用 地址捕获:

C++学习:6、C++ 11新特性;C++ 14;C++ 异常;智能指针

(2)运用 mutable

C++学习:6、C++ 11新特性;C++ 14;C++ 异常;智能指针

留意:

C++学习:6、C++ 11新特性;C++ 14;C++ 异常;智能指针

C++14

1、泛型 lambda

C++学习:6、C++ 11新特性;C++ 14;C++ 异常;智能指针


2、对捕获的变量进行初始化

C++学习:6、C++ 11新特性;C++ 14;C++ 异常;智能指针


C++17

1、能够进行初始化的if、 switch语句 、

  • 变量 a 只为 if else 服务
  • 变量 b 只为 switch 服务

C++学习:6、C++ 11新特性;C++ 14;C++ 异常;智能指针


其他的新的语法特性还没有流行起来。


反常

在编程傍边咱们经常遇到的过错类型:

  • 语法过错:编译器就会提示咱们
  • 逻辑过错:是程序员自己留下的过错。
  • 反常:在程序运转傍边或许呈现,也或许不呈现

比如说在程序在运转进程傍边,内存空间不足

C++学习:6、C++ 11新特性;C++ 14;C++ 异常;智能指针

这个状况比较夸张,可是在实践开发的时分,必定有或许呈现。

  • 每个程序分别写自己的代码,请求的次数多了,必定会形成内存不足。
  • 反常没有被处理,会导致程序停止 。

C++学习:6、C++ 11新特性;C++ 14;C++ 异常;智能指针


1、捕捉

运用 try 和 catch 指令:

1、将或许发生反常的代码,放到 try 里边去。

2、一旦发生反常,就会主动到对应的 catch 傍边履行代码。

  • 从每次发生反常,都会履行 catch 傍边的代码

C++学习:6、C++ 11新特性;C++ 14;C++ 异常;智能指针

改善:咱们呈现反常之后,break 跳出。

C++学习:6、C++ 11新特性;C++ 14;C++ 异常;智能指针


分析流程:

  • 假如没有 break ,在履行完循环之后,也会跳出循环。
  • 有 break 的话,发生反常之后立马会调出循环。

C++学习:6、C++ 11新特性;C++ 14;C++ 异常;智能指针


2、主动抛出

  • 上面的反常是系统本身抛出的反常

  • 有的时分,或许需求咱们自己去主动抛出反常

举例:0 做被除数,咱们要主动抛出反常

C++学习:6、C++ 11新特性;C++ 14;C++ 异常;智能指针

C++学习:6、C++ 11新特性;C++ 14;C++ 异常;智能指针


catch 和 throw 的捕捉类型必须匹配

C++学习:6、C++ 11新特性;C++ 14;C++ 异常;智能指针

C++学习:6、C++ 11新特性;C++ 14;C++ 异常;智能指针

总结:

1、将或许发生反常的代码,放到 try 里边去。

2、一旦发生反常,就会主动到对应的 catch 傍边履行代码。


反常抛出的声明:

C++学习:6、C++ 11新特性;C++ 14;C++ 异常;智能指针


3、自界说反常类型

  • 经过类来界说反常

C++学习:6、C++ 11新特性;C++ 14;C++ 异常;智能指针

  • 经过面向目标的思想,这有什么优势呢?
  • 自己能够添加很多的与反常相关的成员函数。

C++学习:6、C++ 11新特性;C++ 14;C++ 异常;智能指针


4、规范反常

C++学习:6、C++ 11新特性;C++ 14;C++ 异常;智能指针

C++学习:6、C++ 11新特性;C++ 14;C++ 异常;智能指针

C++学习:6、C++ 11新特性;C++ 14;C++ 异常;智能指针


智能指针

传统指针存在的问题

  • 需求手动办理内存
  • 容易发生内存泄露(忘掉开释、呈现反常等)
  • 开释之后发生野指针

内存走漏:该开释内存的时分,没有开释,形成内存越来越少

C++学习:6、C++ 11新特性;C++ 14;C++ 异常;智能指针

指针的开释必须放到最终,并且还得赋值为 nullptr ,避免野指针

C++学习:6、C++ 11新特性;C++ 14;C++ 异常;智能指针

智能指针就不需求这么做

  • auto_ptr 是一个模板类,需求传入指向的目标类型
  • p 是一个目标,相当于将 newPerson()的返回值传给 p 的构造函数
  • p 在栈空间,当 test( ) 履行完毕之后,p就会被开释,然后堆空间的内容也会跟着开释。

C++学习:6、C++ 11新特性;C++ 14;C++ 异常;智能指针

留意:

  • 智能指针创造的意图:在栈空间的指针毁掉时,将堆空间的内存进行开释。

  • 智能指针必须指向堆空间的目标,由于栈空间的目标不需求咱们智能指针进行开释,系统会主动开释。

  • 假如指向栈空间的目标,那么就会形成二次开释


智能指针便是为了解决传统指针存在的问题

  • auto_ptr:归于C++98规范,在C++11中现已不引荐运用(有缺点,比如不能用于数组)
  • shared_ptr:归于C++11规范
  • unique_ptr:归于C++11规范

1、自己完成智能指针

意图:在自己毁掉的时分,开释堆空间。

初步完成:

C++学习:6、C++ 11新特性;C++ 14;C++ 异常;智能指针

缺点:

  • p1 并不是指针,而是一个目标,真实的指针是 m_pointer 成员变量。
  • 所以很不方便。

C++学习:6、C++ 11新特性;C++ 14;C++ 异常;智能指针

改善:将运算符进行重载

C++学习:6、C++ 11新特性;C++ 14;C++ 异常;智能指针

存在的问题:不能存放数组

  • 不能开释全部元素

C++学习:6、C++ 11新特性;C++ 14;C++ 异常;智能指针

改善:

C++学习:6、C++ 11新特性;C++ 14;C++ 异常;智能指针


2、shared_ptr

hared_ptr 的规划理念:

1、多个shared_ptr能够指向同一个目标,当最终一个shared_ptr在效果域范围内完毕时,目标才会被主动开释。

能够经过一个已存在的智能指针初始化一个新的智能指针

  • p1 、 p2、p3、p4 都毁掉的时分, new 的Person 内存才能够进行开释。

C++学习:6、C++ 11新特性;C++ 14;C++ 异常;智能指针

C++学习:6、C++ 11新特性;C++ 14;C++ 异常;智能指针


2、针对数组的用法

C++学习:6、C++ 11新特性;C++ 14;C++ 异常;智能指针


3、一个shared_ptr会对一个目标发生强引证(strong reference)

  • 每个目标都有个与之对应的强引证计数,记录着当时目标被多少个shared_ptr强引证着
  • 能够经过shared_ptr的 use_count 函数获得强引证计数
  • 当有一个新的shared_ptr指向目标时,目标的强引证计数就会+1
  • 当有一个shared_ptr毁掉时(比如效果域完毕),目标的强引证计数就会-1
  • 当一个目标的强引证计数为0时(没有任何shared_ptr指向目标时),目标就会主动毁掉(析构)

多一个指向,强引证个数就会 + 1.少一个,就会减一

C++学习:6、C++ 11新特性;C++ 14;C++ 异常;智能指针

两次开释的状况

C++学习:6、C++ 11新特性;C++ 14;C++ 异常;智能指针


4、shared_ptr的循环引证

会导致内存走漏:

  • Person 类傍边有一个Car 类型的智能指针, m_car (成员变量

  • Car 类傍边有一个 Person 类型的智能指针, m_person (成员变量

  • 在主函数,栈空间傍边创建两个目标,Person 目标 ,Car 目标。

没有循环调用的状况:

C++学习:6、C++ 11新特性;C++ 14;C++ 异常;智能指针


有循环调用的状况:(你中有我,我中有你)

  • 缺点:内存走漏,堆空间无法开释

C++学习:6、C++ 11新特性;C++ 14;C++ 异常;智能指针

内存分布图:

  • Person 目标傍边的 m_car 指向 Car

  • Car 目标傍边的 m_person 指向 Person

  • Car 和 Person 的强引证计数都是 2

C++学习:6、C++ 11新特性;C++ 14;C++ 异常;智能指针

  • 当栈空间开释之后,
  • Car 和 Person 的强引证计数都是 1 ,由于还有强引证计数的存在,所以堆空间不会毁掉
  • shared_ptr 会发生强引证,只要有一个引证没有开释,那么就不会毁掉堆空间

C++学习:6、C++ 11新特性;C++ 14;C++ 异常;智能指针

解决办法:运用弱引证 weak_ptr


3、weak_ptr

  • weak_ptr会对一个目标发生弱引证
  • weak_ptr能够指向目标,解决shared_ptr的循环引证问题

C++学习:6、C++ 11新特性;C++ 14;C++ 异常;智能指针

内存空间:

C++学习:6、C++ 11新特性;C++ 14;C++ 异常;智能指针


4、unique_ptr

  • unique_ptr也会对一个目标发生强引证,它能够确保同一时间只要1个指针指向目标
  • 当unique_ptr 毁掉时(效果域完毕时),其指向的目标也就主动毁掉了
  • 能够运用std::move函数转移unique_ptr的所有权

了解即可