C++中的智能指针(1):shared_ptr 的介绍和用法

原理简介

C++中采用new和delete来创建(申请)和释放(销毁)内存,但是因为释放内存时机把握不当、忘记释放内存等原因,很难准确及时地管理内存。
因此,C++标准库推出了智能指针机制来更好的管理内存,智能指针能自动释放所指向的对象。

shared_ptr

简介

shared_ptr 允许多个指针指向 同一个对象,它基于模板实现,默认初始化的智能指针中保存着一个空指针。

当进行拷贝或者赋值操作时,没个shared_ptr都有一个关联的计数器,通常称其为引用计数

我们每次拷贝一个shared_ptr都会使这个引用计数递增(当局部的shared_ptr离开作用域时,计数器就会递减),当引用计数为0(指向对象的最后一个shared_ptr被销毁)时,shared_ptr会销毁这个对象(通过shared_ptr的析构函数)

用法
创建智能指针

智能指针也是模板,所以我们创建它的方法和所有其它模板一样:

shared_ptr<string> p1;  //指向string的智能指针
shared_ptr<list<int>> p2;   //指向int的list的智能指针
最安全的分配内存的方法:make_shared函数

make_shared函数是标准库函数,也在头文件memory中

//指向一个值为42的int的shared_ptr
shared_ptr<int> p3 = make_shared<int>(42); 
//指向一个值为"9999999999"
shared_ptr<string> p4 = make_shared<string>(10, '9');
//指向一个初始化值的int
shared_ptr<int> p5 = make_shared_ptr<int>();
当然,我们也可以将shared_ptr 和new来结合使用
shared_ptr<int> p1(new int(1024)); //使用直接初始化方式

注意,使用new的话只能使用直接初始化:

shared_ptr<int> p1 = new int(1024); //错误,只能使用直接初始化

注意事项

关于数组的使用和指派删除器

看到这里,我们所有的例子都是单个对象,那数组是不是也可以像这样shared_ptr<int> sp(new int[10]);使用shread_ptr?
这样是错误的。我们要使用shared_ptr管理数组的话,必须给其制定一个删除器(函数):

shared_ptr<int> sp(new int[10], [](int *p) {delete[] p;});

这里的匿名函数即是删除器。
如果没有提供删除器,这段代码就是未定义的。默认情况下,shared_ptr使用delete销毁它所指的对象。如果这个对象是个动态数组,对其使用delete所产生的问题和释放一个动态数组忘记加[]的后果相同。

关于不要混用普通指针和智能指针和以单独语句创建shared_ptr的好处

void func(shared_ptr<int> p3){
    //使用p3
}// p3离开作用域,销毁

int main(){
    int  *a = new int(10);  //危险!x是个普通指针,而不是一个智能指针
    void func(shared_ptr<int>(a)); //危险!内存会被释放
    cout << *a << endl;        //a是个空指针
}

所以,最好的解决方法是使用单独的语句创建shared_ptr。还有,当一个shared_ptr绑定到一个普通指针的时候,我们就将内存管理的任务交给了shared_ptr,我们不应该再用内置指针来管理内存。

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值