C++中智能指针最常用的shared_ptr和unique_ptr

shared_ptr

基本用法: 可以通过构造函数, make_shared辅助函数和reset()方法来初始化shared_ptr

1. 初始化方法

    shared_ptr p1(new int(1));
    shared_ptr p2 = p1;
    shared_ptr p3;
    p3.reset(new int(1));
    shared_ptr p4 = make_shared(int(5));

优先使用make_shared来构造, 更加高效

不能用一个原始指针直接赋值智能指针, 以下方式是错误的

shared_ptr p5=new int(1); //error

2.获取智能指针的原始指针: 通过get方法

    shared_ptr ptr = make_shared(int(5));
    int *p=ptr.get();

3.指定删除器:自定义指针销毁方式

void ptr_deleter(const int*p)
{
    delete p;
}
shared_ptr p(new int, ptr_deleter);

第二个参数指定删除器(一个可调用对象, 其中参数为该类型的指针, 如上面为int*)

当shared_ptr引用计数为0时, 调用传入的而不是默认的删除器来释放对象的内存

当用shared_ptr管理动态数组时, 需要指定删除器, 因为shared_ptr默认删除器不支持数组对象

如下使用lambda表达式作为删除器

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

通过default_delete作为删除器, 同时封装一个make_shared_array函数来支持数组

template
shared_ptr make_shared_array(int size)
{
    return shared_ptr(new T[size],default_delete());
}

(自测)貌似这样也支持数组

shared_ptr ptr(new int[10]);

使用shared_ptr注意

(1)不要用一个原始指针初始化多个shared_ptr

    int *ptr = new int;
    shared_ptr p1(ptr);
    shared_ptr p2(ptr);  //错误

(2)不要在函数实参中创建shared_ptr

function(shared_ptr(new int),g());

参数的计算顺序可能没有固定顺序, 若是new int后执行g()抛出异常, 则shared_ptr还没有创建, 则new int内存泄漏了

(3)不要用this指针构造shared_ptr作为返回值

destructor

destructor

以上代码p1和p2相当于同一个new A初始化, 会shared_ptr销毁时, 会重复析构

正确做法:

让该类继承enable_shared_from_this<>, 同时调用shared_from_this()返回

destructor

只要用shared_ptr, 调用的成员函数里都不能使用this构造, 否则都会出错

另外, 不要在构造函数里使用shared_from_this

(4)避免循环引用

以下代码会由于循环引用, 引用计数值都为1, 导致两个指针都不会析构

//没有输出

unique_ptr

unique_ptr不允许复制, 不允许其他的智能指针共享其内部的指针, 但可以转移

    unique_ptr ptr(new int);
   // unique_ptr ptr2=ptr;    error 不可以赋值
    unique_ptr ptr3=move(ptr); //用move进行转移
    assert(ptr!=nullptr); //转移后ptr为nullptr

自定义make_unique函数且让其支持定长数组

思路

不是数组, 返回unique_ptr

是数组且非定长数组, 返回unique_ptr, 即不应该调用make_unique(10)而是make_unique(10)

最后过滤掉该定长数组(函数声明为delete)

// !is_array_v确定不是数组, 返回unique_ptr
template
enable_if_t,unique_ptr> make_unique_(Args&&...args)
{
    return unique_ptr( new T(forward(args)...));
}
//定长数组如T[10],  不应该调用make_unique(10);而是make_unique(10);
// is_array_v确定是数组且!extent_v确定非定长数组, 返回unique_ptr
template
enable_if_t&&!extent_v,unique_ptr> make_unique_(size_t size)
{
    using U=remove_extent_t;
    return unique_ptr( new U[size]);
}
//否之过滤掉该定长数组
template
enable_if_t,void> make_unique_(Args&&...)=delete;
    unique_ptr ptr= make_unique_(10);
    unique_ptr ptr1= make_unique_(10);

不过unique_ptr本身也支持数组, shared_ptr自测也支持, 如下

    unique_ptr ptr1(new A[10]);
    shared_ptr ptr2(new A[10]);

unique_ptr也支持删除器, 但和shared_ptr有区别, 要指定删除器类型

如果希望lambda删除器捕获变量, 则需要用function包装

    unique_ptr p1(new A[10],[&](A*p){delete []p;});       //错误
    unique_ptr> p2(new A[10],[&](A*p){delete []p;}); //正确

到此这篇关于C++中智能指针最常用的shared_ptr和unique_ptr的文章就介绍到这了,更多相关C++ shared_ptr和unique_ptr内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

你可能感兴趣的:(C++中智能指针最常用的shared_ptr和unique_ptr)