目录

一,什么是智能指针

二,共享的智能指针shared_ptr

1. shared_ptr的初始化

3. 指定删除器

三,独占的智能指针unique_ptr

1. 初始化

2. 删除器

四, 弱引用的智能指针weak_ptr

1 初始化

2.常用函数


前言:面试的时候被问到智能指针了,答的很糟糕,这几天重新学习了智能指针。下面是我对c++智能指针的理解与总结,希望能帮到大家,同时提升自己。

一,什么是智能指针

在C++中没有垃圾回收机制,必须自己释放分配的内存,否则就会造成内存泄露。解决这个问题最有效的方法是使用智能指针(smart pointer)。智能指针是存储指向动态分配(堆)对象指针的类,用于生存期的控制,能够确保在离开指针所在作用域时,自动地销毁动态分配的对象,防止内存泄露。智能指针的核心实现技术是引用计数,每使用它一次,内部引用计数加1,每析构一次内部的引用计数减1,减为0时,删除所指向的堆内存。

  • c++中用的最多的是下面三种智能指针

C++11中提供了三种智能指针,使用这些智能指针时需要引用头文件<memory>

  • std::shared_ptr:共享的智能指针
  • std::unique_ptr:独占的智能指针
  • std::weak_ptr:弱引用的智能指针,它不共享指针,不能操作资源,是用来监视shared_ptr的。
  • 下面对他们分别进行分析

二,共享的智能指针shared_ptr

  • 首先了解一下基本概念,再看代码,会学的很快

1. shared_ptr的初始化

共享智能指针是指多个智能指针可以同时管理同一块有效的内存,共享智能指针shared_ptr 是一个模板类,如果要进行初始化有三种方式:通过构造函数、std::make_shared辅助函数以及reset方法。共享智能指针对象初始化完毕之后就指向了要管理的那块堆内存,如果想要查看当前有多少个智能指针同时管理着这块内存可以使用共享智能指针提供的一个成员函数use_count

2.获取原始指针

对应基础数据类型来说,通过操作智能指针和操作智能指针管理的内存效果是一样的,可以直接完成数据的读写。但是如果共享智能指针管理的是一个对象,那么就需要取出原始内存的地址再操作,可以调用共享智能指针类提供的get()方法得到原始地址

3. 指定删除器

当智能指针管理的内存对应的引用计数变为0的时候,这块内存就会被智能指针析构掉了。另外,我们在初始化智能指针的时候也可以自己指定删除动作,这个删除操作对应的函数被称之为删除器这个删除器函数本质是一个回调函数,我们只需要进行实现,其调用是由智能指针完成的。

  •  上面三个基本知识点了解以后就可以轻松的阅读代码了(代码注释都非常的详细哦!)
#include <iostream>
using namespace std;
#include <string>
#include <memory>class Test
{
public:Test() : m_num(0){cout << "construct Test..." << endl;}Test(int x) : m_num(0){cout << "construct Test, x = " << x << endl;}Test(string str) : m_num(0){cout << "construct Test, str = " << str << endl;}~Test(){cout << "destruct Test..." << endl;}void setValue(int v){this->m_num = v;}void print(){cout << "m_num: " << this->m_num << endl;}private:int m_num;
};int main()
{/*--------------------------  一,初始化智能指针shared_ptr  ------------------------------*///1.通过构造函数初始化shared_ptr<int> ptr1(new int(3));cout << "ptr1管理的内存引用计数: " << ptr1.use_count() << endl;//2.通过移动和拷贝构造函数初始化shared_ptr<int> ptr2 = move(ptr1);cout << "ptr1管理的内存引用计数: " << ptr1.use_count() << endl;cout << "ptr2管理的内存引用计数: " << ptr2.use_count() << endl;shared_ptr<int> ptr3 = ptr2;cout << "ptr2管理的内存引用计数: " << ptr2.use_count() << endl;cout << "ptr3管理的内存引用计数: " << ptr3.use_count() << endl;//3.通过 std::make_shared初始化shared_ptr<int> ptr4 = make_shared<int>(8);shared_ptr<Test> ptr5 = make_shared<Test>(7);shared_ptr<Test> ptr6 = make_shared<Test>("GOOD LUCKLY!");//4.通过reset初始化ptr6.reset(); //重置ptr6, ptr6的引用基数为0cout << "ptr6管理的内存引用计数: " << ptr6.use_count() << endl;ptr5.reset(new Test("hello"));cout << "ptr5管理的内存引用计数: " << ptr5.use_count() << endl;cout << endl;cout << endl;/*--------------------------  二,共享智能指针shared_ptr的使用  ------------------------------*///1.方法一Test* t = ptr5.get();t->setValue(1000);t->print();//2.方法二ptr5->setValue(7777);ptr5->print();printf("\n\n");/*------------------------------------  三,指定删除器  -----------------------------------*///1.简单举例shared_ptr<Test> ppp(new Test(100), [](Test* t) {//释放内存cout << "Test对象的内存被释放了......." << endl;delete t;});printf("----------------------------------------------------------------------\n");2.如果是数组类型的地址,就需要自己写指定删除器,否则内存无法全部释放//shared_ptr<Test> p1(new Test[5], [](Test* t) {//    delete[]t;//    });//3.也可以使用c++给我们提供的 默认删除器函数(函数模板)shared_ptr<Test> p2(new Test[3], default_delete<Test[]>());//4.c++11以后可以这样写 也可以自动释放内存shared_ptr<Test[]> p3(new Test[3]);return 0;
}

 另外,我们还可以自己封装一个函数模板make_shared_array方法来让shared_ptr支持数组,代码如下:

#include <iostream>
#include <memory>
#include <string>
using namespace std;//有了这个函数模板,我们就不用自己去释放数组类型的地址了
template <typename T>
shared_ptr<T> make_share_array(size_t size)
{//返回匿名对象return shared_ptr<T>(new T[size], default_delete<T[]>());
}int main()
{shared_ptr<int> ptr1 = make_share_array<int>(10);cout << ptr1.use_count() << endl;shared_ptr<string> ptr2 = make_share_array<string>(7);cout << ptr2.use_count() << endl;return 0;
}

三,独占的智能指针unique_ptr

  • 首先了解一下基本概念,再看代码,会学的很快

1. 初始化

std::unique_ptr是一个独占型的智能指针,它不允许其他的智能指针共享其内部的指针,可以通过它的构造函数初始化一个独占智能指针对象,但是不允许通过赋值将一个unique_ptr赋值给另一个unique_ptr。

2. 删除器

unique_ptr指定删除器和shared_ptr指定删除器是有区别的,unique_ptr指定删除器的时候需要确定删除器的类型,所以不能像shared_ptr那样直接指定删除器

#include <iostream>
using namespace std;
#include <string>
#include <memory>
#include <functional>class Test
{
public:Test() : m_num(0){cout << "construct Test..." << endl;}Test(int x) : m_num(1){cout << "construct Test, x = " << x << endl;}Test(string str) : m_num(2){cout << "construct Test, str = " << str << endl;}~Test(){cout << "destruct Test..." << endl;}void setValue(int v){this->m_num = v;}void print(){cout << "m_num: " << this->m_num << endl;}private:int m_num;
};int main()
{/*--------------------------  一,初始化智能指针unique_ptr  ------------------------------*///1.通过构造函数初始化unique_ptr<int> ptr1(new int(3));//2.通过移动函数初始化unique_ptr<int> ptr2 = move(ptr1);//.通过reset初始化ptr2.reset(new int(7));/*--------------------------  二,unique_ptr的使用  ------------------------------*///1.方法一unique_ptr<Test> ptr3(new Test(666));Test* pt = ptr3.get();pt->setValue(6);pt->print();//2.方法二ptr3->setValue(777);ptr3->print();/*------------------------------------  三,指定删除器  -----------------------------------*///1.函数指针类型//using ptrFunc = void(*)(Test*);//unique_ptr<Test, ptrFunc> ptr4(new Test("hello"), [](Test* t) {//    cout << "-----------------------" << endl;//    delete t;//    });//2.仿函数类型(利用可调用对象包装器)unique_ptr<Test, function<void(Test*)>> ptr4(new Test("hello"), [](Test* t) {cout << "-----------------------" << endl;delete t;});/*---------- 四,独占(共享)的智能指针可以管理数组类型的地址,能够自动释放 ---------*/unique_ptr<Test[]> ptr5(new Test[3]);//在c++11中shared_ptr不支持下面的写法,c++11以后才支持的shared_ptr<Test[]> ptr6(new Test[3]);return 0;
}

四, 弱引用的智能指针weak_ptr

 弱引用智能指针std::weak_ptr可以看做是shared_ptr的助手,它不管理shared_ptr内部的指针。std::weak_ptr没有重载操作符*->,因为它不共享指针,不能操作资源,所以它的构造不会增加引用计数,析构也不会减少引用计数,它的主要作用就是作为一个旁观者监视shared_ptr中管理的资源是否存在。

1 初始化

#include <iostream>
#include <memory>
using namespace std;int main()
{shared_ptr<int> sp(new int);weak_ptr<int> wp1;weak_ptr<int> wp2(wp1);weak_ptr<int> wp3(sp);weak_ptr<int> wp4;wp4 = sp;weak_ptr<int> wp5;wp5 = wp3;return 0;
}
  1. weak_ptr<int> wp1;构造了一个空weak_ptr对象
  2. weak_ptr<int> wp2(wp1);通过一个空weak_ptr对象构造了另一个空weak_ptr对象
  3. weak_ptr<int> wp3(sp);通过一个shared_ptr对象构造了一个可用的weak_ptr实例对象
  4. wp4 = sp;通过一个shared_ptr对象构造了一个可用的weak_ptr实例对象(这是一个隐式类型转换)
  5. wp5 = wp3;通过一个weak_ptr对象构造了一个可用的weak_ptr实例对象
  •  通过调用std::weak_ptr类提供的use_count()方法可以获得当前所观测资源的引用计数

2.常用函数

  1.  通过调用std::weak_ptr类提供的expired()方法来判断观测的资源是否已经被释放
  2. 通过调用std::weak_ptr类提供的lock()方法来获取管理所监测资源的shared_ptr对象
  3. 通过调用std::weak_ptr类提供的reset()方法来清空对象,使其不监测任何资源
  • 利用weak_ptr可以解决shared_ptr的一些问题
  1. 返回管理this的shared_ptr
  2. 解决循环引用问题

c++11之智能指针相关推荐

  1. C++新特性探究(18.3):C++11 weak_ptr智能指针

    C++11 weak_ptr智能指针 1.weak_ptr指针的创建 2.weak_ptr模板类提供的成员方法 例2: 程序执行结果为: 2 1 10

  2. C++新特性探究(18.2):C++11 unique_ptr智能指针详解

    C++11 unique_ptr智能指针   作为智能指针的一种,unique_ptr 指针自然也具备"在适当时机自动释放堆内存空间"的能力.和shared_ptr指针最大的不同之 ...

  3. C++新特性探究(18.1):C++11 shared_ptr智能指针

      在实际的 C++ 开发中,我们经常会遇到诸如程序运行中突然崩溃.程序运行所用内存越来越多最终不得不重启等问题,这些问题往往都是内存资源管理不当造成的.比如:   有些内存资源已经被释放,但指向它的 ...

  4. c++11中智能指针的原理,使用,实现

    文章目录 理解智能指针的原理 智能指针的使用 shared_ptr的使用 unique_ptr的使用 weak_ptr的使用 循环引用 指针指针的设计和实现: 理解智能指针的原理 c++程序设计中使用 ...

  5. [C++11]共享智能指针shared_ptr指定删除器

    当智能指针管理的内存对应的引用计数变为 0 的时候,这块内存就会被智能指针析构掉了.另外,我们在初始化智能指针的时候也可以自己指定删除动作,这个删除操作对应的函数被称之为删除器,这个删除器函数本质是一 ...

  6. 『C++11』智能指针 匠心之作

    优缺点: 智能指针由原始指针的封装,优点是可以自动分配内存,不用担心内存泄漏问题. 用于解决独占/共享所有权指针的释放,传输等问题. 但是没有原始指针方便. 目录 一. unique_ptr 独占指针 ...

  7. C++11 unique_ptr智能指针详解

    文章目录 0.应用场景 1.初始化方式 2.常用操作 3.例子 例子1 创建unique_ptr并以引用形式传递给函数 例子2 用vector管理unique_ptr 例子3 unique_ptr作为 ...

  8. c++新特性11 (9)智能指针一”_Compressed_pair类“

    功能类似std::pair类,但是是派生关系, key 类有一个value对象 template <class _Ty1, class _Ty2, bool = is_empty_v<_T ...

  9. C++11 使用智能指针封装 pimpl idom

    程序结构如下, 本例主要使用std::unique_ptr封装C++常用的pimpl idom,就是在cpp文件中用一个impl来封装细节.实现部分可以随意修改,但是保持接口部分不变. 这样一来是节省 ...

最新文章

  1. springmvc常见问题汇总
  2. Maven环境变量配置以及修改阿里云镜像
  3. 【内网安全】域横向CobalStrikeSPNRDP
  4. C#方法重载(overload)方法重写(override)隐藏(new)
  5. linux 版本的scipy,Linux 系统中 SciPy (Python 3) 编程环境
  6. entity framework不查数据库修改或排除指定字段集合通用方法
  7. MongoDB 教程六: MongoDB管理:数据导入导出,数据备份恢复及用户安全与认证
  8. 二叉树的迭代遍历(JavaScript)
  9. AndroidStudio打包生成apk
  10. Node:服务器端解决跨域
  11. CentOS:bash: g++: 未找到命令...
  12. 3dMax 单位设置(门)
  13. 【M-PARTNER】魔窗携手心意点点,共创App增长新生态!
  14. 用正则表达式制作单线程小说网站小说下载器
  15. 2、孟子·公孙丑上 孟子·公孙丑下
  16. android 键盘自适应,Android输入框布局如何随键盘变化
  17. 全开源即时通讯(IM)系统-仿微信
  18. hdu 5473 There was a kingdom(dp+几何)
  19. 泰勒展开:一阶,二阶
  20. 情绪识别软件?论程序员对猫的偏爱!

热门文章

  1. 2023 年 31 大功能测试工具
  2. ubuntu下nginx配置静态网页
  3. 使用 Vue 生成 Excel 任务窗格加载项
  4. 想做一名淡泊名利的逐梦者
  5. js 实现随机密码生成
  6. matlab轴向柱塞泵动力学仿真,斜盘式轴向柱塞泵柱塞副油膜特性研究
  7. 基于arduino单片机智能避障小车
  8. Linux的常用指令学习以及LInux的文件目录的简介
  9. 解决从Android studio 粘贴代码到印象笔记格式混乱的问题
  10. 我们的管理:人才成长体系