1.智能指针作用
提出智能指针时候,不得不提一下栈和堆。我们都知道,栈上的资源是由系统管理的,申请和释放资源都是由栈的策略来进行的。
而堆上的资源申请,是用户显示的调用关键字new 和 delete来进行申请资源和释放资源,该资源的生命周期是执行new语句申请资源 到执行 delete释放资源。(或者程序结束由系统释放这部分堆资源)。
这时候我们在来谈一下智能指针的作用和原理。
智能指针就是行为类似指针的栈对象,并非指针类型,在栈对象生命周期即将结束时,智能指针通过析构函数释放有它管理的堆内存。这样就能够不用手动释放内存了。
2.智能指针需要注意什么
(1)智能指针是利用了栈对象生命即将结束时,系统调用析构函数释放对象资源时候,管理它所指向的堆内存。那么我们要是把智能指针本身定义在堆内存上,是不是就不满足上面的特性了。所以智能指针是写在栈上使用的。
(2)智能指针不是指针类型是个对象。所以我们需要它满足指针的特性。那就是能解引用。我们这里需要重载一下 -> 操作符 和 * 操作符。这样我们就让对象有了指针的功能和特性。
(3)接着我们需要思考的问题就是构造时候问题,我们知道构造函数分为四种,默认构造函数,无参数构造函数,有参数的构造函数,拷贝构造函数。我们需要管理一块动态内存。必须要知道内存的起始地址,因此需要有一个参数 内存的起始地址。所以不考虑默认和无参数构造函数。有参数的构造,我们如果把两个相同的地址都传给了智能指针让其构造,产生两个智能指针对象都指向同一个动态内存地址块,析构时候岂不是会对相同的动态内存块释放了两次,这比内存泄漏还要恶劣。假设我们用的是拷贝构造函数。会发生什么,如果是默认拷贝构造,就是浅拷贝,这个也是对相同的内存释放了两次。
(4)赋值运算符的重载
第一步是判断是否是自赋值,然后再释放旧资源,假设这时候还有其他指针指着同一块管理的动态内存,你就这样释放了?然后还有和前面提到一样的问题。相同动态内存地址,被多个智能指针指着。如何解决多次释放相同动态内存的问题。因此我们要引出计数器。我们下面会讲。
嗯智能指针看起来好像有点鸡肋,只要自己知道手动释放资源就够了。这种想法很明显是有问题的。比如说你在写代码时候,如果写了一个if()return 出去了,没执行到下面的delete呢,或者抛出异常,没执行下面的delete呢?
(5)多线程
后面会说
(6)是不是应该设计为单例模式
后面会说
boost库的四种智能指针
auot_ptr scoped_ptr、shared_ptr、weak_ptr
3.auto_ptr
应该有两种稍稍不同的思路写auto_ptr,一种是所有者转移,把原来的智能指针置为NULL,第二种是是在成员变量里定义一个_owner变量,来提供所有权管理的方法。
理解第一种的代码思路:
就是当发生了构造,我之前说了构造出来的一般都要传一个指针指向开辟的堆内存作为参数,或者默认为NULL。然后把外部传进来的指针赋给了要构造的对象,然后把外部传进来的指针赋为NULL。
赋值运算符重载先delete,然后赋值获取新的堆内存的管理权,接着把外部的指针变NULL。这样就始终只有一个智能指针是真正管理到堆内存地址,其他都为空。