C++智能指针原理分析与简单实现

一个简单智能指针实现的思路如下:

  智能指针,简单来讲是使用引用计数的方法,来跟踪监控指针。当引用计数为0时就delete 所跟踪的目标指针,释放内存
  智能指针将一个指针封装到一个类中,当调用智能指针的拷贝构造函数时,将引用计数+1(因为新创建的智能指针也引用了目标指针)
  重载智能指针的赋值操作符,等号左边的对象引用计数-1,右边的对象引用计数+1,右边的目标指针和引用计数赋值给左边的对象
  智能指针的析构函数将引用计数-1,并判断是否为0,如果是的话delete 目标指针

示例如下(为方便测试,加入了输出打印,已屏蔽):

template <class T>
class smart_ptr
{
private:
    T* ptr;
    int* count;
public:
    smart_ptr(T* p=0):ptr(p),count(new int(1))//构造时将引用计数初始化为1
    {
    }
    smart_ptr(const smart_ptr& src)//拷贝构造时引用计数+1
    {
        ++*src.count;
        count=src.count;
        ptr=src.ptr;
        //cout<<"after copy:count is "<<*count<<endl;
    }
    smart_ptr& operator=(const smart_ptr& src)//赋值时左边对象引用计数+1,右边对象引用计数-1
    {
        --*count;
        if(*count==0)//判断计数是否为0,为0立即释放内存
            delete ptr;
        count=src.count;
        ++*count;
        ptr=src.ptr;
        //if(count)cout<<"after fuzhi:count is"<<*count<<endl;
        //else cout<<"mem released"<<endl;
    }
    T* operator->()//重载指针的箭头操作符
    {
        return ptr;
    }
    T& operator*()//重载指针的解引用操作符
    {
        return *ptr;
    }
    ~smart_ptr()//析构中引用计数-1,判断计数是否为0,为0才释放内存
    {
        --*count;
        if(*count==0)
        {
            delete ptr;
            delete count;
            ptr=NULL;
            count=NULL;
        }
        //if(count)cout<<"destructor:count is"<<*count<<endl;
        //else cout<<"mem released"<<endl;
    }
};



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
C++智能指针原理 C++智能指针 1. 智能指针原理 采⽤C++ Primer Plus中作者引出智能指针的⽅式进⾏说明,感觉超好。 ⾸先看2个函数: //函数1 void remodel(std::string & str) { std::string * ps = new std::string(str); ... str = ps; return; } //函数2 void remodel(std::string &str) { std::string * ps = new std::string(str); ... if (weird_thing()) throw exception(); str = *ps; delete ps; return; } 上⾯,函数1每次调⽤都在堆中申请内存,但从未收回,铁定内存泄漏;函数2虽然使⽤了异常,但是代码中出现异常时,delete将不执 ⾏,因此也仍会导致内存泄漏。 分析⼀下问题在哪? 其实不论上⾯remodel()函数是正常终⽌还是异常终⽌的,函数中的指针变量ps⾃⼰占据的内存都将从栈内存中删除,⽽ps指向的新申请到 的堆内存却没有被释放,导致了内存泄漏。所以啊,我们就在想当指针ps⾃⼰占据的内存被释放的时候,它指向的内存也被释放该多好啊。 但问题是ps现在是⼀个常规指针,它⽆法做到这⼀点。那C++中我们想的这件事情谁能帮我们做到呢?那就是类对象的析构函数,当ps是 ⼀个类对象的时候,在ps过期时,它的析构函数释放掉它所指的内存不就完成我们上⾯想要的事情了嘛!这正是C++智能指针原理!! 这个原理就是:⽤具有析构函数的类对象充当指针,当该指针过期时,它的析构函数释放掉它所指的堆内存。 2. C++中4种智能指针模版类的区别 C++中4种智能指针模版类:auto_ptr,unique_ptr,shared_ptr,weak_ptr。 这4种智能指针也全都是基于上⾯的原理实现的。当使⽤这些指针时,是不需要我们⼿动使⽤delete去释放指针所指内存的。 简单的使⽤实例:记得包含头⽂件memory #include <memory> void remodel(std::string &str) { std::string * ps = new std::string(str); str = *ps; return; } 接下来思考⼀个问题,如果你基于上⾯智能指针的思想实现了⼀个智能指针模版类mysmart_ptr。假设使⽤它进⾏内存管理,看下⾯的赋 值语句: mysmart_ptr<string> ps (new string("I reigned lonely as a cloud.")); mysmart_ptr<string> vocation; vocation = ps; 上⾯ps和vocation将指向同⼀个string对象,这样的话,当程序结束时可能会出现删除同⼀个对象两次的现象——⼀次是ps过期时,另⼀ 次是vocation过期的时候,如果想避免这样的问题的话,我们需要想⼀下怎么解决?其实这样的⽅法有多种: 1. 定义赋值运算符,使之执⾏深拷贝。这样两个指针将指向不同的对象,其中的⼀个对象是另⼀个对象的副本。 2. 建⽴所有权(ownership)概念,对于特定的对象,只能有⼀个智能指针可拥有它,这样只有拥有对象的智能指针的构造函数会删除该 对象。然后,让赋值操作转让所有权。这就是⽤于auto_ptr和unique_ptr的策略,但unique_ptr的策略更严格。 3. 创建智能指针更⾼的指针,跟踪引⽤特定对象的智能指针数。这称为引⽤计数(reference counting)。例如,赋值时,计数将加1, ⽽指针过期时,计数将减1。仅当最后⼀个指针过期时,才调⽤delete。这是shared_ptr采⽤的策略。 当然,同样的策略也适⽤于复制构造函数。每种⽅法都有其⽤途。 auto_ptr和unique_ptr: 上⾯也提到了,⽆论是auto_ptr还是unique_ptr,都是基于所有权的概念去解决可能出现的删除⼀个对象两次的问题的。这种情况下会有 什么问题呢?先看auto_ptr,看⼀个⼩例⼦: auto_ptr<string> films[2] = { auto_ptr<string> (new string("Fowl Balls")), auto_ptr<string> (new string("Duck Walks")) }; auto_ptr<string> pwin; pwin = films[0];//注:films[0]对内存失去了所有权 cout << films[0] << endl;//注:会出现错误,因为film[0]指向的内存此时已经

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ctrlturtle

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值