C++ 智能指针类

这篇文章主要来源于:codeguru网站的一篇文章:A TR1 tutorial:smart pointer  (详细介绍了C++的智能指针,尤其是shared_ptr)。

众所周知,在 TR1 之前,C++标准库中的智能指针只有auto_ptr,但由于它的【排他所有权模式】(exclusive ownership model)导致了许多问题,为解决,C++TR1中引入了 boost 开源库中的智能指针:shared_ptr 和 weak_ptr 并使之成为了标准库的一部分(C++11标准)。

注1C++ TR1 即 C++ Technical Report 1 是 ISO/IEC TR 19768, C++ Library Extensions(函数库扩充)的一般名称,它是针对 C++ 标准库的第一次扩展。

注2:C++最新标准:C++11已将智能指针:shared_ptr、weak_ptr收录为标准库中,即对应为:std::shared_ptr, std::weak_ptr,相应的头文件:<memory>(相比TR1:头文件:<tr1/memory>).

注3若读者编译器不支持C++11标准,则编译时:1.将头文件由<memory> 改为 <tr1/memory>; 2.将namespace由 std:: 改为 std::tr1 .


一、智能指针类:std::auto_ptr

 

由于 auto_ptr 基于【排他所有权模式】,这意味着:两个指针(同类型)不能指向同一个资源,复制或赋值都会改变资源的所有权。

一个简单的例子1

#include <iostream>  
#include <memory>  
class A  
{  
public:  
    void print(){std::cout<<"A::print"<<std::endl;}  
};  
int main()  
{  
    std::auto_ptr<A>pa1(new A);  
    pa1->print();  
    std::cout<<"pa1 pointer:"<<pa1.get()<<std::endl;  
  
    std::auto_ptr<A>pa2(pa1); //copy constructor  
    pa2->print();  
    std::cout<<"pa1 pointer:"<<pa1.get()<<std::endl;  
    std::cout<<"pa2 pointer:"<<pa2.get()<<std::endl;  
  
    return 0;  
}

输出



即即经过复制构造之后,pa1所指向资源的所有权转向了pa2,而pa1变成空,二者不能同时共享该资源。

auto_ptr 主要有两大问题

  • 复制和赋值会改变资源的所有权,不符合人的直觉。
  • 在 STL 容器中无法使用auto_ptr ,因为容器内的元素必需支持可复制(copy constructable)和可赋值(assignable)。

二、C++11中新增的智能指针


新加入标准模板库(STL)的智能指针有两个:

shared_ptr:基于引用计数模型。每次有 shared_ptr 对象指向资源,引用计数器就加1;当有 shared_ptr 对象析构时,计数器减1;当计数器值为0时,被指向的资源将会被释放掉。且该类型的指针可复制和可赋值,即其可用于STL容器中。此外,shared_ptr 指针可与多态类型和不完全类型一起使用。主要缺点:无法检测出循环引用(后面会细说),如一颗树,其中既有指向孩子结点的指针又有指向父亲结点的指针,即孩子父亲相互引用。这会造成资源无法释放,从而导致内存泄露。为了 fix 这个问题,引入了另一个智能指针:weak_ptr.

weak_ptr:指向有shared_ptr 指向的资源(即其需要shared_ptr的参与,其辅助 shared_ptr 之用),但是不会导致计数。一旦计数器为0,不管此时指向资源的 weak_ptr 指针有多少,资源都会被释放,而所有的这些 weak_ptr 指针会被标记为无效状态(即 weak_ptr作为观察shared_ptr 的角色存在着,shared_ptr 不会感受到 weak_ptr 的存在)。

上一例子的shared_ptr 实现-例子2

#include <iostream>
#include <memory>
class A
{
public:
    void print(){std::cout<<"A::print"<<std::endl;}
};
int main()
{
    std::shared_ptr<A>sp1(new A); //namespace: std::
    sp1->print();
    std::cout<<"sp1 pointer:"<<sp1.get()<<std::endl;

    std::shared_ptr<A>sp2(sp1); //copy constructor
    sp2->print();
    std::cout<<"sp1 pointer:"<<sp1.get()<<std::endl;
    std::cout<<"sp2 pointer:"<<sp2.get()<<std::endl;

    std::cout<<"count sp1:"<<sp1.use_count()<<std::endl; //get reference count
    std::cout<<"count sp2:"<<sp2.use_count()<<std::endl;

    return 0;
}

输出



可知:sp2创建后,sp1对资源的所有权并没有被剥夺,而是sp1 和 sp2 均指向了资源,且此时资源的引用计数为2。当两个shard_ptr 指针sp1、sp2 超过其作用域时,最后一个析构的指针将会致使资源的释放(因为引用计数为0了)。

三、智能指针类:std::tr1::shared_ptr


3.1 概念

std::shared_ptr 智能指针共享所指向的资源(所有权),即几个 shared_ptr 可同时拥有一个对象,且共享一个控制块(constrol block),包含指向资源的 shared_ptr对象个数、指向资源的 weak_ptr 对象个数以及删除器(deleter:用户自定义的用于释放资源的函数,可以默认没有)。

一个空的 shared_ptr 对象不拥有任何资源和控制块。另一方面,一个 shared_ptr 初始化为一个NULL 指针和一个控制块,这有别有空的 shared_ptr。当共享的引用计数器为0时,资源释放(delete 操作符释放,或由用户提供的

  • 11
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值