c++的内存管理用惯了new和delete手动管理,但是有些场景这种手动管理的方式使用起来很不方便。然后想搞清楚智能指针的用法,常见问题如下:
(0)头文件
#include<memory>
(1)如何初始化
shared_ptr<string> p1 = make_shared<string>(10, '9'); shared_ptr<string> p2 = make_shared<string>("hello"); shared_ptr<string> p3 = make_shared<string>();
std::unique_ptr<int> up;//可以指向int的unique_ptr,不过是空的
up = std::unique_ptr<int>(new int(12));//unique_ptr<T>
std::unique_ptr<string> up1(new string("bianchengzhuji"));
std::unique_ptr<int[]> up2(new int[10]);//数组需要特别注意std::unique_ptr<int> up;//声明空的unique_ptr
int *p= new int(1111);
up.reset(p);//令up指向新的对象,p为内置指针
什么情况需要指定删除器?
如果对象不是new分配的,请传递删除器。
(2)何时会释放资源
当引用计数为0时,shared_ptr所管理的对象自动销毁。
那么哪些情况会影响引用计数呢?
赋值:auto sp = make_shared<int>(1024);//sp的引用计数为1
拷贝:auto sp2 = make_shared<int>(1024); auto sp1(sp2); 容易忽略的就是函数参数拷贝,传值方式会增加引用计数,引用方式则不会增加引用计数。
reset:调用reset会减少计数,sp.reset(),而如果sp是唯一指向该对象的,则该对象被销毁。
(3)二者的区别
首先最明显的区别自然是它们一个是专享对象,一个是共享对象。而正是由于共享,包括要维护引用计数等,它带来的开销相比于unique_ptr来说要大。另外,shared_ptr无法直接处理数组,因为它使用delete来销毁对象,而对于数组,需要用delete[]。因此,需要指定删除器。
相比于shared_ptr,unique_ptr的开销更小,甚至可以说和裸指针相当,它不需要维护引用计数的原子操作等等。
所以说,如果有可能,优先选用unique_ptr。
(4)有哪些禁忌用法
虽然shared_ptr能很大程度避免内存泄漏,但是使用不当,仍然可能导致意外发生。
存放于容器中的shared_ptr
不要使用多个裸指针初始化多个shared_ptr