首页 > 其他分享 >智能指针unique_ptr<>创建的过程

智能指针unique_ptr<>创建的过程

时间:2024-09-13 09:24:39浏览次数:1  
标签:std int new unique ptr 指针

智能指针unique_ptr<>创建的过程

两种初始化方式的比较

std::unique_ptr 可以通过两种方式进行初始化:直接构造或者使用 std::make_unique()。它们之间的区别如下:

直接构造 std::unique_ptr

你可以通过直接构造来创建一个 unique_ptr,如下:

std::unique_ptr<int> ptr(new int(42));
  • 优点
    • 你可以在构造时精确控制对象的构造方式,比如分配自定义的内存管理器。
  • 缺点
    • 这种方式需要手动调用 new,可能会导致意外的内存泄漏。如果 new 分配成功但在接下来分配 std::unique_ptr 之前抛出异常,内存可能会泄漏。
    • 手动调用 new 是一种旧的习惯用法,不符合现代 C++ 的推荐实践。

使用 std::make_unique()

从 C++14 开始,标准库引入了 std::make_unique(),这是现代 C++ 推荐的创建 unique_ptr 的方式:

auto ptr = std::make_unique<int>(42);
  • 优点
    • 安全性make_unique 更加安全,因为它在单一表达式中创建对象并将其所有权交给 unique_ptr,不会出现手动调用 new 时的内存泄漏问题。
    • 简洁性:代码更简洁,不需要显式调用 new,减少手动管理内存的风险。
    • 异常安全性:在 make_unique 内部,内存分配和 unique_ptr 的创建是原子操作。如果在创建过程中发生异常,内存会被自动清理,避免了内存泄漏。
  • 缺点
    • 在需要自定义的删除器或内存管理策略时,make_unique 不如直接使用 unique_ptr 构造函数灵活。

第一种方式的内部细节

  1. 调用 new int(42)

    • new int(42) 会在堆上分配一个 int 对象,并初始化其值为 42。这一步返回一个 原生指针,指向堆上的新对象。
    • 假设这个原生指针为 p_raw,此时 p_raw 是一个指向整数的裸指针。
      int* p_raw = new int(42); // p_raw 是一个原生指针,指向堆上的整数对象

    第一步的结果

    • 产生了一个原生指针 p_raw,它指向堆上分配的 int(42) 对象。
  2. 创建 std::unique_ptr<int> ptr

    • 接下来,std::unique_ptr<int> 的构造函数被调用,接受该原生指针作为参数,并将其托管给 unique_ptr
    • std::unique_ptr 接管了该原生指针的所有权,此时 原生指针 已经不再被使用,所有权转移到了 std::unique_ptr 上。
      std::unique_ptr<int> ptr(p_raw); // ptr 接管了 p_raw 的所有权

    第二步的结果

    • std::unique_ptr 接管了该指针的所有权,并在其生命周期内管理这个堆上的 int 对象。该指针变成了 unique_ptr 内部持有的指针。
  3. 销毁原生指针

    • 在执行完 std::unique_ptr<int> ptr(new int(42)); 这行代码后,堆上对象的所有权只归 unique_ptr,裸指针 p_raw 不再存在(除非你显式声明了它)。

过程总结:

  • 两个指针

    • 第一步:当调用 new int(42) 时,产生了一个 原生指针,它指向新分配的 int 对象。
    • 第二步:std::unique_ptr 的构造函数接受这个原生指针,并接管其所有权,之后该原生指针不再使用。
  • 最终结果

    • 最终,只有一个指针(即 std::unique_ptr 内部持有的指针)管理这个堆上的对象。原生指针在 unique_ptr 接管后不再需要使用。

 

标签:std,int,new,unique,ptr,指针
From: https://www.cnblogs.com/smartljy/p/18411601

相关文章

  • 指针初阶及使用
    指针的使用指针是什么指针和指针类型野指针指针运算指针和数组二级指针指针数组指针是什么我们对指针的理解大多数就是地址,那究竟是不是呢?指针是内存中一个最小单元的编号,也就是地址平时口语中说的指针,通常指的是指针变量,是用来存放内存地址的变量我们想要了解......
  • 深入理解指针(5)
    1.sizeof和strlen的对⽐在学习操作符的时候,我们学习了sizeof,sizeof计算变量所占内存内存空间⼤⼩的,单位是字节,如果操作数是类型的话,计算的是使⽤类型创建的变量所占内存空间的⼤⼩。sizeof只关注占⽤内存空间的⼤⼩,不在乎内存中存放什么数据。 strlen是C语⾔库函数......
  • 关于指针(4)的期末复习
    1.回调函数是什么?回调函数就是⼀个通过函数指针调⽤的函数。如果你把函数的指针(地址)作为参数传递给另⼀个函数,当这个指针被⽤来调⽤其所指向的函数时,被调⽤的函数就是回调函数。回调函数不是由该函数的实现⽅直接调⽤,⽽是在特定的事件或条件发⽣时由另外的⼀⽅调⽤的,⽤于......
  • 【每日一题】LeetCode 2576.求出最多标记下标(贪心、数组、双指针、二分查找、排序)
    【每日一题】LeetCode2576.求出最多标记下标(贪心、数组、双指针、二分查找、排序)题目描述给定一个整数数组nums,数组下标从0开始。你需要执行以下操作,直到无法再执行为止:选择两个互不相同且未标记的下标i和j。满足条件2*nums[i]<=nums[j],则标记下标i和j。......
  • C语言深入理解指针六(19)
    文章目录前言一、sizeof&strlensizeofstrlensizeof和strlen的对比二、数组和指针笔试题解析一维数组字符数组二维数组三、指针运算笔试题解析题目1题目2题目3题目4题目5题目6题目7总结前言  本篇都将是练习题,从而让你对指针的理解更上一层楼一、sizeof&s......
  • C++ 指针
    声明int*ipl,*ip2;//ipl和ip2都是指向int型对象的指针doubledp,*dp2;//dp2是指向double型对象的指针,dp是double型对象因为引用不是对象,没有实际地址,所以不能定义指向引用的指针。指针值指针的值(即地址)应属下列4种状态之一:指向一个对象。指向紧邻对象所占空......
  • 【C语言基础】指针
    1指针与地址,指针变量地址就是内存区中对每个字节的编号。如整型变量a、b、c,整型变量需要4个字节,分配的地址分别为1000、1004、1008。可以通过访问变量的地址来找到所需的变量,我们称变量的地址为变量的“指针”。上例中的1000、1004、1008分别为变量a、b、c的指针。指针变量......
  • 什么时候使用指针?什么时候使用引用?什么时候应该按值传递
    在平时开发过程中,会遇到传参类型选择的问题。使用引用传值的主要原因:1、调用者可修改函数中的数据值;2、传输过程中,仅传递了引用,提高了函数调用效率;类型    仅读值,不写值读值+写值内置数据类型    值传递(较小内存)指针传递数组指针传递指针传递结构体指针或引......
  • C++最强功能之一指针
    最是人间留不住,朱颜辞镜花辞树。                            ——《蝶恋花·阅尽天涯离别苦》【清】王国维今天我们来说一说这个C++区别其他语言最明显的功能,指针。C++的指针可以说是功能强大,很多游戏的外挂中核......
  • [1060] Create the unique ID from the index (DataFrame, GeoDataFrame)
    Thereareseveralwaystoimplementit!Hereisasampledataset:importpandasaspd#SampleDataFramedf=pd.DataFrame({'A':[1,2,3,4],'B':[None,5,None,7]})1.pd.Series()#ConverttheindextoaSerieslikeac......