一般来讲C++中对于指针指向的对象需要使用new主动分配堆空间,在使用结束后还需要主动调用delete释放这个堆空间。为了使得自动、异常安全的对象生存期管理可行,就出现了智能指针这个概念。简单来看智能指针是 RAII(Resource Acquisition Is Initialization,资源获取即初始化) 机制对普通指针进行的一层封装。这样使得智能指针的行为动作像一个指针,本质上却是一个对象,这样可以方便管理一个对象的生命周期。
注:智能指针和原生指针不要混用,使用不当可能会导致程序异常;
智能指针(动态内存管理)头文件 <memroy>
1 class SmartPointer 2 { 3 public: 4 SmartPointer() 5 { 6 cout << "SmartPointer::SmartPointer()" << endl; 7 } 8 ~SmartPointer() 9 { 10 11 cout << "SmartPointer::~SmartPointer()" << endl; 12 } 13 };
unique_ptr<SmartPointer> ptest1(new SmartPointer("空格")); // unique_ptr<SmartPointer> ptest2 = ptest1; //此时编译报错
unique_ptr<SmartPointer> ptest1(new SmartPointer("空格")); cout << "ptest1 location: " << ptest1.get() << endl; unique_ptr<SmartPointer> ptest2 = move(ptest1); //将ptest1指向对象所有权转移给ptest2,ptest1置空为NULL cout << "ptest2 location: " << ptest2.get() << endl; unique_ptr<SmartPointer> ptest3(ptest2.release()); //将ptest2指向对象所有权转移给ptest3,ptest2置空为NULL cout << "ptest3 location: " << ptest2.get() << endl;
结果为:
unique_ptr
本身拥有的几个主要方法:unique_ptr<SmartPointer> ptest1(new SmartPointer()); ptest1.reset(new SmartPointer()); //释放销毁原有对象,持有新对象 ptest1.reset(); //直接释放销毁原对象 ptest1 = nullptr; //同上
共享权,多个shared_ptr同时拥有一个原生指针(内存)的所有权,最后一个拥有者负责原生指针的释放和销毁;
std::shared_ptr<SmartPointer> pTest1(new SmartPointer()); std::shared_ptr<SmartPointer> pTest2 = pTest1; //编译正常,允许所有权的共享 cout << "pTest1 location: " << pTest1.get() << endl; cout << "pTest2 location: " << pTest2.get() << endl; shared_ptr<SmartPointer> pTest3 = make_shared<SmartPointer>();//新建共享指针方法,make_shared效果类似new pTest2 = pTest3; cout << "pTest3 location: " << pTest3.get() << endl; cout << "pTest2 location: " << pTest2.get() << endl;
结果:
共享指针类中包括一个成员函数用来记住所管理的内存当前有多少个指针指向它;
use_count()方法可以获取指向对象的shared_ptr个数;
shared_ptr<string> pStr_1(new string("霜之哀伤")); shared_ptr<string> pStr_2 = make_shared<string>("火之高兴"); auto pStr_3 = pStr_1; //此时指向“霜之哀伤”数量为2,“火之高兴”为1; cout << *pStr_1 << " : " << pStr_1.use_count() << "\t" << *pStr_2 << " : " << pStr_2.use_count() << endl; pStr_3 = pStr_2; //此时指向“霜之哀伤”数量为1,“火之高兴”为2; cout << *pStr_1 << " : " << pStr_1.use_count() << "\t" << *pStr_2 << " : " << pStr_2.use_count() << endl;
结果:
shared_ptr<SmartPointer> pTest1(new SmartPointer()); cout << pTest1.unique() << endl; //此时为true; shared_ptr<SmartPointer> pTest2 = pTest1; cout << pTest1.unique() << endl; //此时为false pTest1.reset(new SmartPointer()); //释放销毁原有对象,持有新对象 pTest1.reset(); //直接释放销毁原对象 pTest1 = nullptr; //同上
结果:
class B; class A { public: A() { cout << "A::A()" << endl; } ~A() { cout << "A::~A()" << endl; } shared_ptr<B> pB; }; class B { public: B() { cout << "B::B()" << endl; } ~B() { cout << "B::~B()" << endl; } shared_ptr<A> pA; };
weak_ptr是为了辅助shared_ptr所引入的弱引用智能指针,主要是为了解决shared_ptr中循环引用(对象A持有对象B,对象B持有对象A,此时两个对象的引用计数均为2;在跳出作用范围时,两个对象引用计数均减1但还有1,导致跳出作用范围后两个对象的资源没有释放销毁,产生内存泄漏)的问题。
shared_ptr<A> pA(new A()); //新建A类对象 shared_ptr<B> pB(new B()); //新建B类对象 pA->pB = pB; //A类中持有B类 pB->pA = pA; //B类中持有A类 //此时构成了循环引用 cout << pA.use_count() << endl; cout << pB.use_count() << endl;
结果:
循环引用在跳出作用范围时未调用类A与类B析构函数,导致内存泄漏,此时可以将类内的shared_ptr改为weak_ptr可以避免;
weak_ptr不能直接使用原生指针构造,可以使用一个shared_ptr和另一个weak_ptr进行构造;
weak_ptr
拥有的几个主要方法shared_ptr<A> pA(new A()); weak_ptr<A> weak_pA = pA; //弱指针,不增加引用计数 cout << "A引用计数:" << weak_pA.use_count() << endl; shared_ptr<A> pA_1 = weak_pA.lock(); //此时又一个shared_ptr指向原生指针,计数加1 cout << "A引用计数:" << weak_pA.use_count() << endl; cout << weak_pA.expired() << endl; //销毁原生指针 pA.reset(); pA_1.reset(); cout << weak_pA.expired() << endl; weak_pA.reset(); //置空weak_ptr
结果:
https://www.cnblogs.com/corineru/p/10895249.html
https://www.cnblogs.com/TenosDoIt/p/3456704.html
https://zhuanlan.zhihu.com/p/436290273
https://www.csdn.net/tags/MtTaEg0sMTkwMTctYmxvZwO0O0OO0O0O.html
搜索
复制