我的编程空间,编程开发者的网络收藏夹
学习永远不晚

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

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

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

shared_ptr

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

1. 初始化方法

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

shared_ptr<int[]> ptr(new int[10]);

使用shared_ptr注意

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

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

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

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

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

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

class A
{
public:
    shared_ptr<A> get_self()
    {
        return shared_ptr<A>(this);
    }
    ~A()
    {
        cout << ("destructor") << endl;
    }
};
int main()
{
    shared_ptr<A> p1(new A);
    shared_ptr<A> p2 = p1->get_self();
    return 0;
}

destructor

destructor

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

正确做法:

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

class A :public enable_shared_from_this<A>    //继承
{
public:
    shared_ptr<A> get_self()
    {
        return shared_from_this();            //调用该函数
    }
    ~A()
    {
        cout << ("destructor") << endl;
    }
};
int main()
{
    shared_ptr<A> p1(new A);
    shared_ptr<A> p2 = p1->get_self();
    return 0;
}

destructor

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

class A
{
public:
    void test()
    {
        shared_ptr<A>(this); //错误
    }
    ~A()
    {
        cout<<(  "destructor"  )<<endl;
    }
};
shared_ptr<A> p(new A);
p->test()

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

(4)避免循环引用

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

class A;
class B;
class A
{
public:
    shared_ptr<B> b_ptr;
    ~A()
    {
        cout << ("A destructor") << endl;
    }
};
class B
{
public:
    shared_ptr<A> a_ptr;
    ~B()
    {
        cout << ("B destructor") << endl;
    }
};
int main()
{
    shared_ptr<A> a_p(new A);
    shared_ptr<B> b_p(new B);
    a_p->b_ptr=b_p;
    b_p->a_ptr=a_p;
}

//没有输出

unique_ptr

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

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

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

思路

不是数组, 返回unique_ptr<T>

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

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

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

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

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

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

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

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

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

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

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

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

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

C++智能指针shared_ptr怎么使用

本篇内容介绍了“C++智能指针shared_ptr怎么使用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1、什么是shared_ptr?C+
2023-06-29

C语言智能指针shared_ptr和weak_ptr怎么用

这篇文章主要讲解了“C语言智能指针shared_ptr和weak_ptr怎么用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C语言智能指针shared_ptr和weak_ptr怎么用”吧!w
2023-06-30

怎么进行c++智能指针unique_ptr的使用

怎么进行c++智能指针unique_ptr的使用,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。1.为什么需要unique_ptr与shared_ptr作用类似,需要解决内存
2023-06-22

C++11智能指针unique_ptr有什么作用

这篇文章主要讲解了“C++11智能指针unique_ptr有什么作用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C++11智能指针unique_ptr有什么作用”吧!软件开发中有很多处理是
2023-06-19

C++智能指针之shared_ptr如何使用

这篇文章主要介绍“C++智能指针之shared_ptr如何使用”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“C++智能指针之shared_ptr如何使用”文章能帮助大家解决问题。std::share
2023-06-30

C++11智能指针shared_ptr怎么使用

本篇内容介绍了“C++11智能指针shared_ptr怎么使用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!shared_prt的本身是一个
2023-06-19

C/C++中智能指针的用法详解

C/C++中,指针是一个非常重要的概念,其强大但也麻烦,麻烦之处就在于一旦你申请了内存,那就必须要手动去释放内容,否则就会造成内存泄漏。所以智能指针的作用就是防止我们麻痹大意忘记释放内存,帮助我们管理内存的,本文就来聊聊智能指针的用法
2023-01-04

深入了解C++中常用的三个智能指针

C++是一门强大的编程语言,但是在内存管理方面却存在着一些问题。手动管理内存不仅费时费力,而且容易出错。因此,C++中引入了智能指针这一概念,以更好地管理内存,下面就来详细讲讲C++中常用的三个智能指针吧
2023-05-18

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录