智能指针的实现原理及使用

C/C++的内存管理比较繁琐,在使用C++编程时经常从堆上申请内存(new),当使用完毕后我们需要将申请的内存归还(delete)。一般情况下我们申请一次就得释放一次,即new多少内存就delete多少。所以在C++中new和delete是成对出现的。但是当我们申请(new)了一部分内存而在释放(delete)之前程序返回或没有执行到delete处程序抛出异常结束了,那么我们申请的内存就无法归还给操作系统,这样就造成了内存泄漏。为了避免内存泄漏在C++中引入了智能指针的概念。
智能指针:智能指针是一个类,在这个类的构造函数中传入一个普通的指针,在类的析构函数中的该指针进行delete释放。智能指针在栈上开辟内存,所以当函数或程序结束后会自动释放内存空间。C99版本的智能指针有auto_ ptr,C11引入了两种智能指针,不带引用计数的智能指针unique_ptr、weak_ptr 和带引用计数的智能指针share_ptr,而在C11中将auto_ptr 摒弃了。

  • auto_ptr

    • 使用时存在许多问题:无法复制(拷贝构造)和赋值(operator = ),这是因为如果两个或两个以上指针同时指向同一快内存时会对这块内存执行多次delete操作,对已经释放了的内存再次执行delete释放时会造成程序运行崩溃,这是很严重的错误。但执行复制和赋值时编译不会报错。因为不能复制,所以无法作为容器的元素使用。
  • unique_ptr

    • 该智能指针是C++11引入的用于完善auto_ptr 的一个智能指针,unique_ptr 也不支持复制和赋值操作,但它比auto_ptr 做得好的是执行复制和赋值操作会在编译时报错。因此,它可以作为容器的元素使用。如果非要执行赋值则需使用std::move。例如:
std::unique_ptr<int> p1(new int(5));
std::unique_ptr<int> p2 = p1; // 编译会出错
std::unique_ptr<int> p3 = std::move(p1); // 转移所有权, 现在那块内存归p3所有, p1成为无效的指针.
  • shared_ptr

    • C++11或boost的shared_ptr,基于引用计数的智能指针。可随意赋值,直到内存的引用计数为0的时候这个内存会被释放。引用计数原理是统计指向该内存地址的指针个数,当个数大于0时析构不做delete操作,只是将该指针指向NULL,当引用计数为0时析构执行delete操作,并将指针指向NULL。从这里我们可以看出,引用计数对于所有指向该内存块的指针是共享的,第一个指针指向该内存时初始值为1,每当新的指针指向该内存块的时候,计数器执行+1操作,每当有一个指针要释放该内存块的时候先执行-1操作,如果此时计数器值为0,则delete释放,否则只对指针赋NULL。
  • weak_ptr

    • C++11或boost的weak_ptr,弱引用。 引用计数有一个问题就是互相引用形成环,这样两个指针指向的内存都无法释放。需要手动打破循环引用或使用weak_ptr。顾名思义,weak_ptr是一个弱引用,只引用,不计数。如果一块内存被shared_ptr和weak_ptr同时引用,当所有shared_ptr析构了之后,不管还有没有weak_ptr引用该内存,内存也会被释放。所以weak_ptr不保证它指向的内存一定是有效的,在使用之前需要检查weak_ptr是否为空指针。

智能指针的实现及使用
代码来源: https://blog.csdn.net/worldwindjp/article/details/18843087

template <typename T>
class SmartPointer {
public:
    //构造函数
    SmartPointer(T* p=0): _ptr(p), _reference_count(new size_t){
        if(p)
            *_reference_count = 1; 
        else
            *_reference_count = 0; 
    }
    //拷贝构造函数
    SmartPointer(const SmartPointer& src) {
        if(this!=&src) {
            _ptr = src._ptr;
            _reference_count = src._reference_count;
            (*_reference_count)++;
        }
    }
    //重载赋值操作符
    SmartPointer& operator=(const SmartPointer& src) {
        if(_ptr==src._ptr) {
            return *this;
        }
        releaseCount();
        _ptr = src._ptr;
        _reference_count = src._reference_count;
        (*_reference_count)++;
        return *this;
    }

    //重载操作符
    T& operator*() {
        if(ptr) {
            return *_ptr;
        }
        //throw exception
    }
    //重载操作符
    T* operator->() {
        if(ptr) {
            return _ptr;
        }
        //throw exception
    }
    //析构函数
    ~SmartPointer() {
        if (--(*_reference_count) == 0) {
            delete _ptr;
            delete _reference_count;
        }
    }
private:
    T *_ptr;
        size_t *_reference_count;
        void releaseCount() {
        if(_ptr) {
            (*_reference_count)--;
                if((*_reference_count)==0) {
                    delete _ptr;
                    delete _reference_count;
                }
        }
        }
};

int main() 
{
    SmartPointer<char> cp1(new char('a'));
    SmartPointer<char> cp2(cp1);
    SmartPointer<char> cp3;
    cp3 = cp2;
    cp3 = cp1;
    cp3 = cp3;
    SmartPointer<char> cp4(new char('b'));
    cp3 = cp4;
}
发布了62 篇原创文章 · 获赞 68 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/magic_world_wow/article/details/81392739
今日推荐