C++_unique_ptr_一个类Frame的普通指针fr初始化一个unique_ptr, 这个普通指针还有管理权吗?

news/2024/12/22 11:04:14/

一个类Frame的普通指针fr初始化一个unique_ptr, 这个普通指针还有管理权吗?

在 C++ 中,std::unique_ptr 是一种智能指针,它独占管理其所指向对象的所有权。一旦你用一个普通指针初始化或赋值给一个 std::unique_ptr,这个 unique_ptr 会接管对象的所有权,并且不允许其他指针管理这个对象的生命周期。

让我们来看如下代码示例:

Frame* fr = new Frame(); // 普通指针,动态分配内存 
mypFrame = std::unique_ptr<Frame>(fr); // 用普通指针初始化unique_ptr

解释:

  1. Frame* fr = new Frame();

    • 这行代码动态分配了一个 Frame 对象,并用普通指针 fr 指向它。此时 fr 拥有对 Frame 对象的管理权,负责释放该对象的内存。
  2. mypFrame = std::unique_ptr<Frame>(fr);

    • 这行代码将普通指针 fr 赋给了一个 std::unique_ptrmypFrame 现在接管了 fr 所指向的对象的管理权。
    • 一旦 mypFrame 拥有了对象的所有权,普通指针 fr不再拥有管理权,并且你不能再安全地使用 fr 进行内存管理。尤其是,fr 不应被 delete,否则会导致 双重释放 的问题,因为 mypFrame 会在超出作用域时自动释放该对象。

重要注意:

  • 普通指针 fr 不再具有管理权:虽然 fr 仍然可以指向该对象,但它不再负责释放内存。现在 std::unique_ptr 拥有该对象的所有权并将在合适的时候释放它。
  • 如果你尝试对 fr 执行 delete fr;,这会导致 双重释放(Double Free)问题,因为 std::unique_ptr 会自动在其析构时释放 Frame 对象。

进一步说明:

  • std::unique_ptr 通过其构造函数接管对象的所有权。这意味着对象的生命周期完全由 unique_ptr 控制,而普通指针 fr 丧失了管理权。
  • 在使用 unique_ptr 后,最好将 fr 置为 nullptr 或停止使用它,因为它不再安全地管理对象。

安全使用示例:

Frame* fr = new Frame(); // 普通指针 
std::unique_ptr<Frame> mypFrame(fr); // 将管理权转移给unique_ptr 
fr = nullptr; // 明确将普通指针设为nullptr以防止错误使用

在这个示例中,我们显式地将 fr 设置为 nullptr,以避免意外地使用它来管理已被 unique_ptr 接管的内存。

总结:

  • 一旦 std::unique_ptr 接管了普通指针指向的对象,普通指针将 不再拥有管理权
  • 在转移所有权后,避免使用普通指针来操作该对象,尤其是不要手动调用 delete,以防止内存管理问题。

mypFrame = std::unique_ptr<Frame>(fr); 时, 会对 fr所指向的Frame对象进行析构吗?

在执行 mypFrame = std::unique_ptr<Frame>(fr); 时,不会立即对 fr 所指向的 Frame 对象进行析构。实际上,此时只是将 fr 所指向的对象的管理权转移给了 std::unique_ptr。具体过程如下:

过程解释:

Frame* fr = new Frame(); // 动态分配内存,fr指向一个新的Frame对象 
mypFrame = std::unique_ptr<Frame>(fr); // 将fr指向的对象的管理权转移给unique_ptr
  1. Frame* fr = new Frame();

    • 这行代码在堆上动态分配了一个 Frame 对象,并返回一个指向该对象的普通指针 fr。此时 fr 负责管理这个 Frame 对象的内存,只有通过 delete fr; 才能释放这个对象。
  2. mypFrame = std::unique_ptr<Frame>(fr);

    • 这行代码创建了一个 std::unique_ptr<Frame>,将 fr 所指向的对象的管理权交给 mypFrame
    • 这里 std::unique_ptr 接管了 fr 的指针,但 不会析构或释放 Frame 对象,因为此时 unique_ptr 还没有释放对象的时机。只有当 mypFrame 离开作用域或被重新赋值时,才会对其管理的对象进行析构。
    • 注意fr 仍然可以指向那个 Frame 对象,但它不再拥有管理权,也不应被手动 delete,否则会导致 std::unique_ptr 之后进行双重释放。

何时析构:

对象的析构发生在 std::unique_ptr 销毁或重新赋值时,而不是在初始化时。因此,Frame 对象会在以下情况下被析构:

  1. mypFrame 离开其作用域时
    • 如果 mypFrame 是一个局部变量,当它离开作用域时,std::unique_ptr 的析构函数会被调用,自动释放它所管理的 Frame 对象,并调用该对象的析构函数。
  2. mypFrame 被赋值为另一个 std::unique_ptr
    • 如果 mypFrame 之前已经管理了一个对象,在赋值前会先释放当前管理的对象,然后接管新对象。例如:
mypFrame = std::make_unique<Frame>(); // 先析构原对象,然后管理新对象

小结:

  • 不会立即析构:当你执行 mypFrame = std::unique_ptr<Frame>(fr); 时,fr 所指向的 Frame 对象不会被立即析构,而是将对象的管理权转移给 mypFrame
  • 何时析构Frame 对象的析构发生在 std::unique_ptr 被销毁、超出作用域或被赋值新的对象时。
  • 避免手动删除 fr:一旦 unique_ptr 接管对象,fr 不再拥有管理权,手动调用 delete 会导致双重释放问题。

http://www.ppmy.cn/news/1533253.html

相关文章

excel 处理数据的常用场景之考勤表的制作

文章目录 预备知识数据有效性excel的图表知识 考勤表效果图开始制作1. 首先我们去分析这个表格&#xff0c;我们把它分为三个部分如下&#xff1a;2. 开始第一个部分的制作3. 开始制作第二部分。4. 第三部分也是最复杂的&#xff0c;因为会用到几个公式&#xff0c;我这里下面会…

uniapp app 端通过webview引入外部 js , webview 与 app 通信

背景 用户登录需要接入腾讯的无感验证&#xff0c;在 index.html 文件里引入 js 文件是不生效的。查看官网相关内容&#xff0c;app 引入只支持 webview 的形式&#xff0c;因为他的 js 文件里面会用到浏览器里的变量&#xff0c;因此就算下载到本地引入也无法使用。 当前项目…

2024年主流前端框架的比较和选择指南

在选择前端框架时&#xff0c;开发者通常会考虑多个因素&#xff0c;包括框架的功能、性能、易用性、社区支持和学习曲线等。以下是一些主流前端框架的比较和选择指南。 1. 主流前端框架简介 React 优点: 组件化开发&#xff0c;易于复用和维护。虚拟DOM提高了性能。强大的生…

25中国烟草校园招聘面试问题总结 烟草面试全流程及面试攻略

开头附上工作招聘面试必备问题噢~~包括综合面试题、无领导小组面试题资源文件免费&#xff01;全文干货。 工作招聘无领导小组面试全攻略最常见面试题&#xff08;第一部分&#xff09;共有17章可用于国企私企合资企业工作招聘面试面试必备心得面试总结资源-CSDN文库https://d…

计算机网络:三次握手和四次挥手详解

三次握手和四次挥手 三次握手 概念 为什么需要握手&#xff1a;握手的作用就是为了同步一些信息&#xff0c;比如最大滑动窗口 TCP&#xff1a;是一个可靠的连接&#xff0c;也就是客户端和服务器双方必须感知对方的存在&#xff0c;也就是需要经历一个建立连接的过程 用三…

【Verilog学习日常】—牛客网刷题—Verilog企业真题—VL63

并串转换 描述 题目描述&#xff1a; 设计一个模块进行并串转换&#xff0c;要求每四位d输为转到一位dout输出&#xff0c;输出valid_in表示此时的输入有效。 信号示意图&#xff1a; clk为时钟 rst为低电平复位 valid_in 表示输入有效 d 信号输入 dout 信号输出 …

SQL_over_partition_by_order_by

在SQL中&#xff0c;OVER子句通常与窗口函数一起使用&#xff0c;用于定义窗口的规则。PARTITION BY用于将数据分成多个独立的分区&#xff0c;而ORDER BY用于在每个分区内定义数据的排序方式。 窗口函数可以对一组行执行计算&#xff0c;并返回计算结果。这些行与当前行有某种…

【07】纯血鸿蒙HarmonyOS NEXT星河版开发0基础学习笔记-Swiper轮播组件与样式结构重用

序言&#xff1a; 本文详细讲解了关于我们在页面上经常看到的轮播图在鸿蒙开发中如何用Swiper实现&#xff0c;介绍了Swiper的基本用法与属性&#xff0c;及如何面对大段的重复代码进行封装和重用&#xff08;Extend、Styles、Builder&#xff09;&#xff0c;使代码更加简洁易…