(1)什么是智能指针:
智能指针(smart pointer)是存储指向动态分配(堆)对象指针的类,用于生存期控制,能够确保自动正确的销毁动态分配的对象,防止内存泄露(利用自动调用类的析构函数来释放内存)。
原理:智能指针类将一个计数器与类指向的对象相关联,通过计数来记录该类有多少个对象共享同一指针。每次创建类的新对象时,初始化指针并将引用计数置1;当对象作为另一对象的副本而创建时,拷贝构造函数拷贝指针并增加与之相应的引用计数;调用析构函数时,构造函数减少引用计数(如果引用计数减至0,则删除基础对象)。
(2)为什么要用智能指针:
手动malloc/new出来的资源,容易忘记free/delete;中途抛出异常,无法释放资源。
(3)常见智能指针介绍:
C++中有四个智能指针,auto_ptr、unique_ptr、shared_ptr、weak_ptr,后三个是C++11支持,第一个已经被11弃用。
auto_ptr:
采用所有权模式,不支持复制和赋值,但是复制和赋值时不会报错,而是剥夺所有权给新的指针。
auto_ptr<string> p1 (new string (“abcd”)); //声明智能指针p1
auto_ptr<string> p2; //声明智能指针p2
p2 = p1; //不报错,但再次访问p1会出错
unique_ptr:
替换auto_ptr,实现独占是拥有或者严格拥有,保证同一时间内只有一个智能指针拥有该对象,复制和赋值会报错。
unique _ptr<string> p1 (new string (“abcd”)); //声明智能指针p1
unique_ptr<string> p2; //声明智能指针p2
p2 = p1; //报错!
shared_ptr:
实现共享式拥有,可随意的复制和赋值,通过计数器的机制记录资源被几个指针所共享,当计数器为0时,资源被释放。
可用use_count()来查看资源所有者的个数,unique()返回资源是否独占所有权,
weak_ptr:
其是一种不控制生命周期的智能指针,指向一个shared_ptr管理的资源对象(shared_ptr是对该资源进行内存管理的强引用),weak_ptr只是提供了对管理资源对象的一个访问手段。
weak_ptr用于解决shared_ptr相互引用时产生的死锁问题,若两个shared_ptr相互引用会导致计数器永远不为0,从而无法释放资源,这也是智能指针的内存泄漏问题,
(4)智能指针的实现:
#include<bits/stdc++.h> using namespace std; template<typename T> //模板类: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; } //重载操作符-> T* operator->(){ if(_ptr) return _ptr; } //析构函数 ~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(newchar('a')); SmartPointer<char> cp2(cp1); SmartPointer<char> cp3; cp3=cp2; cp3=cp1; cp3=cp3; SmartPointer<char> cp4(newchar('b')); cp3 = cp4; }