《C++ Primer》 读书笔记——第十二章 动态内存

第十二章 动态内存

12.1 动态内存和智能指针

1、new和delete

C++的动态内存管理是通过new和delete来完成的
new:在动态内存中为对象分配空间并返回一个指向该对象的指针,我们可以选择对对象进行初始化
delete:接受一个动态对象指针,摧毁该对象,并释放与之相关的内存
我们经常会忘记delete,所以推荐使用智能指针

2、三种智能指针

shared_ptr:允许多个指针指向同一个对象
unique_ptr:“独占”所指向的对象
weak_ptr:是一种弱引用,指向shared_ptr所管理的对象
这三种类型都定义在memory头文件

3、shared_ptr类

智能指针也是模板,在使用时需要提供相应的类型
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

①、make_shared函数

使用该函数获得智能指针是最安全的:
在这里插入图片描述

②、引用计数

在这里插入图片描述
在这里插入图片描述

③、智能指针自动摧毁

当引用计数为0时,智能指针的析构函数会自动销毁对象并且释放它占用的内存
当动态对象不再被使用时,会自动释放动态对象。(共享指针被声明为局部变量)
当存在其它共享指针也指向这块内存时,它就不会被释放掉。(函数返回一个共享指针)

④、使用动态内存的三个原因
  • 程序不知道自己需要使用多少对象
  • 程序不知道所需对象的准确类型
  • 程序需要在多个对象间共享数据

4、直接管理内存

①、使用new动态分配和初始化对象

在这里插入图片描述
在这里插入图片描述
可以直接使用直接初始化和列表初始化:
在这里插入图片描述
可以使用值初始化:
在这里插入图片描述

②、动态分配的const对象

在这里插入图片描述

③、内存耗尽

在这里插入图片描述

④、释放动态内存

在这里插入图片描述

  • 传给delete的指针必须是动态分配的内存,或者是空指针
  • 释放一块非new分配的内存,或者将相同的指针值释放多次,其行为都是未定义的
    在这里插入图片描述
  • 通常情况下,编译器不能分辨一个指针指向的是静态还是动态分配的对象
  • 编译器也不能分辨一个指针所指向的内存是否已经被释放了

因为编译器不能分辨这几种可能会发生错误的情况,所以在我们手动管理动态内存分配时需要十分注意!

⑤、动态对象的生存期到被释放时为止

在这里插入图片描述在这里插入图片描述
两种正确写法:
在这里插入图片描述
在这里插入图片描述

⑥、动态内存管理常见的三个问题
  1. 忘记delete内容。这会导致内存泄漏,而且这种错误不容易找出来
  2. 使用已经释放掉的对象。通过在释放内存后将指针置为空,有时可以检测出这种错误
  3. 同一块内存释放两次。当有多个指针指向相同的动态分配对象时,可能会发生这种情况。
⑦、空悬指针

空悬指针:指向一块曾经保存数据对象但现在已经无效的内存的指针。(被delete的指针)
在delete之后将nullptr赋予指针可以避免误用空悬指针引发的错误。

5、shared_ptr和new结合使用

①、使用new返回的指针来初始化智能指针

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

②、不要混用普通指针和智能指针

在这里插入图片描述
在上面的例子中,接收了x作为参数的智能指针传进了函数。在离开函数作用域后,智能指针的引用计数变为0,该智能指针会被销毁,而智能指针指向的内存会被释放。
x指向的内存被释放后,x就变成了一个空悬指针。使用该空悬指针将会发生错误。
当一个智能指针绑定到一个普通指针时,我们就将内存的管理责任交给了这个智能指针,一旦这样做,我们就不应该再使用内置指针来访问智能指针所指向的内存了!

③、不要使用get初始化另一个智能指针或者为智能指针赋值

在这里插入图片描述

6、智能指针和异常

①、异常处理时智能指针的用途

在这里插入图片描述
在这里插入图片描述
有时候会漏写delete

②、为没有析构函数的类使用智能指针

在这里插入图片描述

③、智能指针陷阱

在这里插入图片描述

7、unique_ptr

在这里插入图片描述
relase只会返回指针,放弃对指针的控制权,并不会释放指针

unique指针不能拷贝,因为它是唯一的

存在特例情况可以拷贝unique指针:拷贝或赋值一个将要被毁灭的unique指针:

  • 可以作为返回值返回
    在这里插入图片描述
  • 可以返回一个局部对象的拷贝
    在这里插入图片描述

8、weak_ptr

在这里插入图片描述
弱类型指针需要绑定到共享指针上,并且不会改变共享指针的引用计数

一旦共享指针被销毁,弱指针指向的对象也会被释放。

12.2 动态数组

值得一提的时,再应用可变大小数组的场景时,容器比动态数组要更好!

1、new和数组

①、使用new分配一个对象数组

在这里插入图片描述
得到的动态数组并不是一个数组类型,所以不能使用begin或end,也不能使用范围for循环
在这里插入图片描述

②、初始化动态分配对象的数组

在这里插入图片描述
内置类型最好采用值初始化,否则将会是未初始化的状态。使用未初始化状态的变量将会引发错误

③、释放动态数组

在这里插入图片描述

④、智能指针和动态数组

在这里插入图片描述
类型方框中必须带有方括号[] ,这样才能说明是一个动态数组

不能使用点和箭头成员运算符

可以使用下标运算符访问数组中的元素

2、allocatir类

①、什么时候用

在这里插入图片描述

②、用法

allocator类定义在头文件memory
在这里插入图片描述
一个简单的例子:
在这里插入图片描述

③、allocator分配的是未构造的内存

在这里插入图片描述

④、摧毁元素

在这里插入图片描述

⑤、释放内存

在这里插入图片描述

⑥、拷贝和填充未初始化内存的算法

这些函数同样是定义在memory头文件
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值