智能指针本身是个类,程序员在为指针进行内存分配后,可能忘记使用delete销毁内存,为了避免这个问题,出现了智能指针。智能指针在创建时调用构造函数,在消亡时(超出使用范围以后)自动调用析构函数,这样就起到一个内存回收的作用。智能指针的对象都是栈上创建。
2、四种智能指针讲解
2.1 std::auto_ptr
std::auto_ptr属于C++98方案,C++11已经弃用。不支持复制(拷贝构造函数)和赋值(operator =),但进行该操作时编译器不会报错。该指针采用所有权模式,假设有std::auto_ptr p1和p2,此时p1已经初始化,将p1赋值给p2,则p2剥夺了p1的所有权,当程序运行时访问p1会报错,因为此时p1所指位置并不确定,因此存在潜在内存问题。
2.2 std::unique_ptr
std::unique_ptr是C++11中新增的用来替代auto_ptr的智能指针。std::unique_ptr实现独占式拥有或严格拥有概念,保证同一时间内只有一个只能指针可以指向该对象,同时智能指针本身是一个类,在对象生命周期结束以后会自动调用析构函数释放内存,从而避免了内存泄漏问题。那么刚才说的有关std::auto_ptr出现的情况如果用std::unique_ptr替换则无法通过编译,需要赋值时调用std::move方法。
2.3 std::shared_ptr
std::shared_ptr实现共享式拥有,多个智能指针可以指向一个相同对象,该对象和其相关资源会在最后一个引用被销毁时释放。std::shared_ptr是为了解决std::auto_ptr在对象所有权上的局限性,在使用引用计数的机制上提供了可以共享所有权的智能指针。
2.4 std::weak_ptr
std::weak_ptr是一中不控制对象生命周期的智能指针,属于弱引用。它指向一个std::shared_ptr管理的对象,其设计的目的是为了配合std::shared_ptr的使用,它只能从一个std::shared_ptr或另一个std::weak_ptr对象构造,其构造和析构不会引起引用计数的增加或减少。std::weak_ptr是用来解决std::shared_ptr相互引用时的死锁问题(如果两个std::shared_ptr相互引用,那么这两个指针的引用计数永远不可能降到0,资源永远不能释放)。
#include <memory>
#include <iostream> template <typename T> class MySharedPtr { private: T *_ptr; size_t *_reference_count;
// 引用计数操作 void __releaseCount() { if(_ptr) { (*_reference_count)--; if(*_reference_count == 0) { delete _ptr; delete _reference_count; } } } public: // 构造函数 MySharedPtr(T *p = nullptr): _ptr(p), _reference_count(new size_t) { if(p) *_reference_count = 1; else *_reference_count = 0; } // 复制构造函数 MySharedPtr(const MySharedPtr &s_p) { if(this != &s_p) { _ptr = s_p._ptr; _reference_count = s_p._reference_count; (*_reference_count)++; } } // 析构函数 ~MySharedPtr() { if(--(*_reference_count) == 0) { delete _ptr; delete _reference_count; } } // 赋值操作符重载 MySharedPtr& operator=(const MySharedPtr &s_p) { if(_ptr == s_p._ptr) return *this; __releaseCount(); _ptr = s_p._ptr; _reference_count = s_p._reference_count; (*_reference_count)++; return *this; } // ->操作符重载 T* operator->() { if(_ptr) return _ptr; } // 指针取值操作符重载 T& operator*() { if(_ptr) return *_ptr; } };
// test