为了解决C++内存泄漏的问题,C++11引入了智能指针(Smart Pointer)。ios
智能指针的原理是,接受一个申请好的内存地址,构造一个保存在栈上的智能指针对象,C++中有一个重要原则,在函数结束时(不管是正常返回,仍是由于异常除法的对战回退),会将全部栈对象销毁,也就是会调用全部栈对象的析构函数。智能指针内部保存的内存也就被释放掉了(除非将智能指针保存起来)。数组
C++11提供了三种智能指针:std::shared_ptr, std::unique_ptr, std::weak_ptr,使用时需添加头文件<memory>。安全
shared_ptr使用引用计数,每个shared_ptr的拷贝都指向相同的内存。每使用他一次,内部的引用计数加1,每析构一次,内部的引用计数减1,减为0时,删除所指向的堆内存。shared_ptr内部的引用计数是安全的,可是对象的读取须要加锁。函数
(1)初始化this
能够经过构造函数、std::make_shared<T>辅助函数和reset方法来初始化shared_ptrspa
#include "stdio.h" #include<memory> #include<iostream> using namespace std; void main() { shared_ptr<int> p1(new int(10)); cout << "p1的引用计数:"<<p1.use_count() << endl; shared_ptr<int> p2 = p1; cout << "p1的引用计数:" << p1.use_count() << " p2的引用计数:" << p2.use_count() << endl; p2.reset(new int(2)); // 当智能指针中有值时,调用rest会使引用计数减1 cout << "p1的引用计数:" << p1.use_count() << " p2的引用计数:" << p2.use_count() << endl; cout << *p2 << endl; p2.reset(); cout << "p1的引用计数:" << p1.use_count() << " p2的引用计数:" << p2.use_count() << endl; shared_ptr<int> p3 = make_shared<int>(20); shared_ptr<int> p4; p4.reset(new int(30)); cout << "p4的引用计数:" << p4.use_count() << endl; }
注意:不能将一个原始指针直接赋值给一个智能指针指针
std::shared_ptr<int> p4 = new int(1);// error
reset()包含两个操做。当智能指针中有值的时候,调用reset()会使引用计数减1.当调用reset(new xxx())从新赋值时,智能指针首先是生成新对象,而后将就对象的引用计数减1(固然,若是发现引用计数为0时,则析构旧对象),而后将新对象的指针交给智能指针保管。rest
(2)获取原始指针code
std::shared_ptr<int> p4(new int(5)); int *pInt = p4.get();
(3)指定删除器对象
智能指针能够指定删除器,当智能指针的引用计数为0时,自动调用指定的删除器来释放内存。std::shared_ptr能够指定删除器的一个缘由是其默认删除器不支持数组对象,这一点须要注意。
template<class T, class D> shared_ptr(T *p, D d)
void DeleteIntPtr(int *p) { delete p; } shared_ptr<int> p(new int(1), DeleteIntPtr);
当咱们使用shared_ptr管理动态数组时,须要指定删除器,由于std::shared_ptr的默认删除器不支持数组对象
shared_ptr<int> p(new int[10], [](int *p){delete[] p;});
也可使用syd::default_delete做为删除器,default_delete的内部是经过调用delete来实现的
shared_ptr<int> p(new int[10], deault_delete<int[]>);
(4)注意make_share和make_arrar_share的使用
(5)使用shared_ptr注意事项
a. 不要用一个原始指针初始化初始化多个shared_ptr
b. 不要在函数实参中建立shared_ptr
unique_ptr是一个独占型的智能指针,它不容许其它的智能指针共享其内部的指针,不容许经过赋值将一个unique_ptr赋值给另一个unique_ptr,unique_ptr不容许复制,但能够经过函数返回给其它的unique_ptr,还能够经过move来转移到其它的unique_ptr,这样它自己就再拥有原来指针的全部权。
注意:unique_ptr不支持make_share
弱引用指针week_ptr是用来监视shared_ptr的,不会使引用计数加1,它无论理shared_ptr内部的指针,week_ptr没有重载操做符,不共享指针,不操做资源。weak_ptr指针能够用来返回this指针和解决循环引用的问题
(1)use_count获取当前观测资源的引用计数
shared_ptr<int> p(new int(1)); weak_ptr<int> p1(p); cout << p1.use_count() <<endl;
(2)经过expired()来判断观测的资源是否已经被释放
(3)经过lock()来获取监视的shared_ptr
(4)weak_ptr返回this指针
不能直接将this指针返回为shared_ptr,须要经过派生std::enable_shared_from_this类,并经过其方法shared_from_this来返回智能指针,缘由是enable_shared_from_this类中有一个weak_ptr指针,这个weak_ptr用来观测this智能指针,调用shared_from_this,会调用内部的weak_ptr的lock()方法
(5 )weak_ptr解决循环引用的问题
#include "stdio.h" #include<memory> #include<iostream> using namespace std; class B; class A { public: shared_ptr<B> bptr; ~A() { cout << "A is delete!" << endl; } }; class B { public: shared_ptr<A> aptr; ~B() { cout << "B is delete!" << endl; } }; void main() { { shared_ptr<A> a(new A()); shared_ptr<B> b(new B()); a->bptr = b; b->aptr = a; cout << "A的引用计数:" << a.use_count() << endl; cout << "B的引用计数:" << b.use_count() << endl; } int i = 0; }
离开做用域后引用计数减1,不会去删除指针,致使内存泄漏
经过weak_ptr解决该问题,只要将A或B中的任意一个成员改为weak_ptr便可