c++primer第十二章动态内存小结-12

100 篇文章 8 订阅

第十二章---动态内存

1.动态内存


C++中,动态内存管理是通过一对运算符完成的:new和delete。C语言中通过malloc与free函数来实现先动态内存的分配与释放,
C++中new与delete的实现其实会调用malloc与free。由于 C++ 语言没有自动内存回收机制,每次 new 出来的内存都要手动 delete。程序员忘记 delete,流程太复杂,最终导致没有 delete,异常导致程序过早退出,没有执行 delete 的情况并不罕见。


new运算其实分为三个部分,

a.首先调用operator new函数分配足够大的为类型化的内存空间以保存指定类型的一个对象,

b.然后运行该对象的构造函数,初始化该对象,

c.最后返回指向新分配内存空间的指针

我们可以重载operator new函数,人为地进行内存分配,达到优化内存的效果。在类中一旦出现重载的operator new函数,则系统不再调用标准库的operator new函数。


delete运算使用时分为两个步骤,

a.首先调用指定对象的析构函数

b.然后调用名为operator delete的标准库函数释放该对象所占用的内存。

c.指针置NULL.否则成为野指针。

operator delete函数同样可以重载。当使用new新建一个动态对象以后需要使用assert判断动态建立是否成功,以防止程序运行时对未建立的对象进行使用。delete数组时需使用[]注明。如果动态建立一个数组而使用了delete去释放它,会导致只有数组中第一个素被释放,出现内存泄漏。


2.智能指针
       

用智能指针便可以有效缓解上述问题,C++11新标准提供了两种智能指针,负责自动释放所指向的对象。

shared_ptr允许多个指针指向同一个对象

unique_ptr则"独占"所指向的对象

标准库还定义了一个名为weak_ptr的伴随类;

这三种类型都定义在memory头文件中。对于编译器来说,智能指针实际上是一个栈对象,并非指针类型,在栈对象生命期即将结束时,智能指针通过析构函数释放有它管理的堆内存。所有智能指针都重载了“operator->”操作符,直接返回对象的引用,用以操作对象。访问智能指针原来的方法则使用“.”操作符。访问智能指针包含的裸指针则可以用 get() 函数。由于智能指针是一个对象,所以if (my_smart_object)永远为真,要判断智能指针的裸指针是否为空,需要这样判断:if (my_smart_object.get()) 智能指针包含了 reset() 方法,如果不传递参数(或者传递 NULL),则智能指针会释放当前管理的内存。如果传递一个对象,则智能指针会释放当前对象,来管理新传入的对象。


3.使用智能指针的一些注意事项

3.1 接受指针参数的智能指针构造函数是explicit(避免只有一个参数的函数进行隐式转换)的,我们不能将一个内置指针隐式转换为一个智能指针。 直接初始初始化可以。

3.2 为了向不能使用智能指针的代码传递一个内置指针,智能指针定义了一个名为get的函数,返回一个普通类型的指针,使用get返回的指针的代码不能delete此指针,因为智能指针会删除,手动删除会造成二次删除

3.3 将一个智能指针绑定到get返回的指针也是错误的。永远不要用get初始化另一个智能指针或者为另一个智能指针赋值。因为普通指针不能自动转化为智能指针。

3.4 当将一个shared_ptr 绑定到一个普通指针时,我们就将内存管理交给了shared_ptr,之后我们就不应该使用内置指针来访问shared_ptr指向的内存了。使用内置指针来访问智能指针所附则的对象是非常危险的,我们不知道对象何时被销毁。


4.share_ptr

make_shared是一个非成员函数,具有给共享对象分配内存,并且只分配一次内存的优点,和显式通过构造函数初始化(new)的shared_ptr相比较,后者需要至少两次分配内存。这些额外的开销有可能会导致内存溢出的问题,最安全的使用动态内存的方法是使用一个make_shared的函数。此函数在动态内存中分配一个对象并初始化,返回指向此对象的shared_ptr。我们可以认为每个shared_ptr都有一个关联的计数器,通常称其为引用计数,无论我们拷贝一个share_ptr,计数器都会递增。当我们给一个shared_ptr赋值或者shared被销毁,计数器就会递减。当用一个shared_ptr初始化另外一个shared_ptr,或将它作为参数传递给一个函数以及作为函数的返回值(赋值给其他的),计数器都会递增一旦一个share_ptr的计数器变为0,它就会释放自己所管理的对象!注意标准库是用计数器还是其他数据结构来记录有多少个指针共享对象由标准库来决定,关键是智能指针类能记录有多少个shared_ptr指向相同的对象,并能在恰当的时候自动释放对象。


5.unique_ptr

一个unique_ptr 拥有它所指向的对象,和shared_ptr不同,某个时刻只能有一个unique_ptr 指向一个给定对象,当unique_ptr 被销毁时,对象也被销毁,unique没有类似make_shared,必须手动new,将其绑定,由于unique_ptr独占它所指向的对象,因此他不支持普通的拷贝和赋值.但是有种特殊的拷贝可以支持:我们可以拷贝或赋值一个即将要被销毁的unique_ptr。


6.weak ptr 

它指向由一个shared_ptr 管理的对象,当我们创建一个weak_ptr 必须用一个 shared_ptr 初始化。引入lock和expired是防止在weak_ptr 不知情的情况下,shared_ptr 被释放掉,weak_ptr 不会更改shared_ptr 的引用计数。



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值