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

版权声明:本博客的所有内容采用Creative Commons(知识共享)许可证,作者权利:署名(BY)& 非商业性使用(NC)。转载时请务必标明文章超链接、作者信息和本声明,禁止用于商业用途。 https://blog.csdn.net/thinkerleo1997/article/details/78754919

原理简介

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,我们不应该再用内置指针来管理内存。

阅读更多

没有更多推荐了,返回首页