智能指针

众所周知,在C++11以前,C++的内存释放是众多程序员头疼的问题,这也是导致使用C++开发效率低下的原因之一,为此C++11引入了智能指针这个概念。

原理

智能指针实际上采用引用计数的方法,调用构造函数时,引用计数默认初始化为1,每一个对象负责维护对象所有引用的计数值。当一个新的引用指向对象时,引用计数器就递增,当去掉一个引用时,引用计数就递减。当引用计数到零时,该对象就将释放占有的资源。

实现

在C++11中,智能指针采用类模板,该类模板包含了一个引用计数的类。程序员定义的每个类,编译器就会让该类继承引用计数的类。代码实现:

class RefCount {
public:
    RefCount():crefs(0) {}
    virtual ~RefCount() {}
    
    void upCount() {
        ++crefs;
    }
    void downCount() {
        if(--crefs == 0)
            delete this;
    }
    
private:
    int crefs;
};

template<typename T>
class SmartPtr{
public:
    SmartPtr(T* p): ptr(p) {
        ptr->upCount();
    }
    ~SmartPtr() {}
    
    T* operator ->() const {
        return ptr;
    }
    
    T& operator *() const {
        return *ptr;
    }
    
    SmartPtr& operator =(T* p) {
        ptr->downCount();
        p->upCount();
        ptr = p;
        return *this;
    }
    
    SmartPtr(const SmartPtr<T>& p) {
        ptr = p;
        ptr->upCount();
    }
    operator T*() const {
        return ptr;
    }
    
    SmartPtr& operator = (SmartPtr<T>& p) {
        return operator =((T*)p);
    }
private:
    T* ptr;  
};

C++11中的 智能指针

share_ptr 允许多个指针指向同一个对象;
unique_ptr 则单独占有一个对象;
weak_ptr 是一种弱引用, 指向 share_ptr 所管理的对象。

推荐使用make_shared 而不是 new

使用make_shared就能在分配对象的同时将 shared_ptr 与之绑定,从而避免无意中将同一内存绑定到多个独立创建的shared_ptr 上

weak_ptr可以用来解决循环引用

因为 weak_ptr 是弱引用,weak_ptr 的构造和析构不会导致引用计数的增加或者减少
例如:

#include <iostream>
#include <memory>
using namespace std;
class B;
class A {
public:
    shared_ptr<B> pb;
    //weak_ptr<B> pb;
    A() {
        cout << "construct A " << endl;
    }
    ~A() {
        cout << "deconstruct A" << endl;
    }
};
class B {
public:
    shared_ptr<A> pa;
    //weak_ptr<A> pa;
    B() {
        cout << "construct B" << endl;
    }
    ~B() {
        cout << "deconstruct B" << endl;
    }
};
int main() {
    shared_ptr<A> ptrA(new A());
    shared_ptr<B> ptrB(new B());
    cout << ptrA.use_count() << endl;
    cout << ptrB.use_count() << endl;
    ptrA->pb = ptrB;
    ptrB->pa = ptrA;
    cout << ptrA.use_count() << endl;
    cout << ptrB.use_count() << endl;
    return 0;
}

如果使用 share_ptr 在构造函数内,结果将输出

construct A
construct B
1
1
2
2

并没有调用析构函数,导致内存泄漏
如果使用 weak_ptr 在构造函数内,结果将输出

construct A
construct B
1
1
1
1
deconstruct B
deconstruct A

正确调用析构函数,内存被全部释放

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 原作者:Babu_Abdulsalam 本文翻译自CodeProject,转载请注明出处。 引入### Ooops...
    卡巴拉的树阅读 30,172评论 13 74
  • C++智能指针 原文链接:http://blog.csdn.net/xiaohu2022/article/deta...
    小白将阅读 6,894评论 2 21
  • 导读## 最近在补看《C++ Primer Plus》第六版,这的确是本好书,其中关于智能指针的章节解析的非常清晰...
    小敏纸阅读 2,020评论 1 12
  • 1. 什么是智能指针? 智能指针是行为类似于指针的类对象,但这种对象还有其他功能。 2. 为什么设计智能指针? 引...
    MinoyJet阅读 646评论 0 1
  • C++ 智能指针详解 一、简介由于 C++ 语言没有自动内存回收机制,程序员每次 new 出来的内存都要手动 de...
    yangqi916阅读 1,386评论 0 2