美文网首页
智能指针

智能指针

作者: 狗尾巴草败了 | 来源:发表于2017-08-13 20:31 被阅读0次

    众所周知,在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

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

    相关文章

      网友评论

          本文标题:智能指针

          本文链接:https://www.haomeiwen.com/subject/yaverxtx.html