智能指针的实现以及原理

C/C++给了开发人员极大的权限来管理程序中堆内存的分配和释放,然而结果却并不如人意:程序开发的过程中经常会遇到内存释放错误导致程序崩溃或者是内存泄漏等问题。伴随着技术的不断发展,内存管理所导致的问题也不断凸显,于是C++11引入了一种新的技术——智能指针来管理程序中的堆内存释放。

智能指针原理

了解智能指针需要了解以下几点:

  • 智能指针本质是一个模板类
  • 声明一个智能指针候其实是声明了一个栈对象,其能够自动释放内存也是基于这一点
  • 每一个智能指针都关联了一块内存空间,并且记录了共用该块内存空间的智能指针的数量。该智能指针对象由于出栈被销毁并且引用计数为0时,释放该内存。

智能指针的设计和实现

是否释放当前内存和智能指针内的引用计数是否为0密切相关,具体以下操作会导致引用计数的改变:

  • 调用构造函数,使用一个指针来初始化智能指针,该指针非空引用计数为1,否则为0
  • 调用拷贝构造函数,利用一个已经存在的智能指针来初始化新对象,这种情况下拷贝对应的指针并增加对应的引用计数
  • 进行赋值操作,调用左侧的对象的析构函数,拷贝右侧的指针到左侧,增加赋值运算符右侧的引用计数
  • 调用析构函数会减少一次引用计数
template <typename T>
class SmartPointer
{
public:
    SmartPointer(T *p):_ptr(p),_reference_count(new size_t)
    {
        if (p)
        {
            *_reference_count = 1;
        }
        else
        {
            *_reference_count = 0;
        }
        std::cout << "SmartPointer(T *p)" << "  ----->--  "<< *_reference_count << endl;
    }

    SmartPointer(const SmartPointer &p):_ptr(p._ptr), _reference_count(p._reference_count)
    {
        if (this == &p)
        {
            return;
        }
        
        if (_ptr != nullptr)
        {
            (*_reference_count)++;
        }
    }

    SmartPointer& operator = (const SmartPointer &src)
    {
        if (this->_ptr == src._ptr)
        {
            return *this;
        }
        checkRelease();
        this->_ptr = src._ptr;
        this->_reference_count = src._reference_count;
        (*this->_reference_count)++;
        return *this;
    }

    ~SmartPointer()
    {
        checkRelease();
    }

    void checkRelease()
    {
        if (*_reference_count == 0 || --(*_reference_count) == 0)
        {
            cout << "Delete!" << endl;
            delete _reference_count;
            _reference_count = nullptr;
            delete _ptr;
            _ptr = nullptr;
        }
    }

    T* operator->()
    {
        return _ptr;
    }
    
    T& operator*()
    {
        if(this->_ptr)
        return *(this->_ptr);
    }

    size_t getUseCount()
    {
        return *(this->_reference_count);
    }
private:
    T * _ptr;
    size_t * _reference_count;
};

使用智能指针

void testFun()
{
    //////////////////////////////////////////////////////////////////////////
    SmartPointer<int> sp0(new int(10));
    SmartPointer<int> sp1(new int(10));
    std::cout << sp0.getUseCount() << endl;
    std::cout << sp1.getUseCount() << endl;

    sp1 = sp0;

    std::cout << sp0.getUseCount() << endl;
    std::cout << sp1.getUseCount() << endl;

    SmartPointer<int> sp2 = sp1;
    std::cout << sp0.getUseCount() << endl;
    std::cout << sp1.getUseCount() << endl;
    std::cout << sp2.getUseCount() << endl;

    //////////////////////////////////////////////////////////////////////////
    SmartPointer<int> sp4(nullptr);
    std::cout << sp4.getUseCount() << endl;

    SmartPointer<int> sp5 = sp4;
    std::cout << sp5.getUseCount() << endl;
}

运行结果

SmartPointer(T *p)  ----->  1
SmartPointer(T *p)  ----->  1
1
1
Delete!
2
2
3
3
3
SmartPointer(T *p)  ----->  0
0
0
Delete!
Delete!

文章版权:My-World - 勿于浮沙筑高台

本文链接:http://doachieveit.cn/index.php/archives/50.html

版权声明:本文为作者原创,转载请注明文章原始出处 !

添加新评论