c++11新特性——endable_shared_from_this

news2025/3/12 14:05:33

文章目录

  • 一.解决场景
    • 代码示例
    • 原因
  • 二.解决办法
    • 代码
  • 三.底层原理


一.解决场景

一个share_ptr管理的类,如果从类的函数里返回类对象(this指针),导致share_ptr引用计数错误,析构时异常问题

代码示例

#include <memory>
#include <iostream>

class Bad
{
public:
std::shared_ptr<Bad> getptr() {
return std::shared_ptr<Bad>(this);
}
~Bad() { std::cout << "Bad::~Bad() called" << std::endl; }
};

int main()
{
// 错误的示例,每个shared_ptr都认为自己是对象仅有的所有者
std::shared_ptr<Bad> bp1(new Bad());
std::shared_ptr<Bad> bp2 = bp1->getptr();
// 打印bp1和bp2的引用计数
std::cout << "bp1.use_count() = " << bp1.use_count() << std::endl;
std::cout << "bp2.use_count() = " << bp2.use_count() << std::endl;
} // Bad 对象将会被删除两次

在这里插入图片描述

原因

2个非共享的share_ptr指向同一个对象,未增加引用计数导对象被析构两次

二.解决办法

继承 std::enable_shared_from_this ,则会为该类 T 提供成员函数: shared_from_this 。 当 T 类型对象 t 被一个为名为 pt 的 std::shared_ptr 类对象管理时,调用 T::shared_from_this 成员函数,将会返回一个新的 std::shared_ptr 对象,它与 pt 共享 t 的所有权。

代码

#include <memory>
#include <iostream>

struct Good : std::enable_shared_from_this<Good> // 注意:继承
{
public:
std::shared_ptr<Good> getptr() {
return shared_from_this();
}
~Good() { std::cout << "Good::~Good() called" << std::endl; }
};

int main()
{
// 大括号用于限制作用域,这样智能指针就能在system("pause")之前析构
{
std::shared_ptr<Good> gp1(new Good());
std::shared_ptr<Good> gp2 = gp1->getptr();
// 打印gp1和gp2的引用计数
std::cout << "gp1.use_count() = " << gp1.use_count() << std::endl;
std::cout << "gp2.use_count() = " << gp2.use_count() << std::endl;
}
system("pause");
}

在这里插入图片描述

三.底层原理

通过继承enable_shared_from_this,然后调用share_from_this(),返回父类enable_shared_from_this的指针,然后shared_ptr在构造是检查是否可以将其转化来判断是否继承enable_shared_from_this

// 定义 enable_shared_from_this 模板类
template <typename T>
class enable_shared_from_this {
public:
    std::shared_ptr<T> shared_from_this() {
        return weak_this_.lock();  // 使用 weak_ptr 创建 shared_ptr
    }

protected:
    // 构造函数,默认初始化 weak_this_
    enable_shared_from_this() {}

private:
    std::weak_ptr<T> weak_this_;  // 用于存储对象的 weak_ptr

    // 允许 shared_ptr 访问私有成员
    template <typename U>
    friend class std::shared_ptr;
};

// 自定义 shared_ptr 的构造函数
template <typename T>
class shared_ptr {
public:
    shared_ptr(T* ptr) : ptr_(ptr) {
        // 检查对象是否继承自 enable_shared_from_this
        if (auto enable_shared = dynamic_cast<enable_shared_from_this<T>*>(ptr)) {
            enable_shared->weak_this_ = *this;  // 初始化 weak_this_
        }
    }

    // 其他 shared_ptr 成员函数...

private:
    T* ptr_;  // 实际管理的对象指针
};

// 示例类继承 enable_shared_from_this
class MyClass : public enable_shared_from_this<MyClass> {
public:
    void func() {
        std::shared_ptr<MyClass> self = shared_from_this();  // 获取指向自身的 shared_ptr
        // 使用 self 进行操作...
    }
};

// 使用示例
int main() {
    std::shared_ptr<MyClass> obj = std::make_shared<MyClass>();
    obj->func();  // 正确使用 shared_from_this()
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2129259.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

最近试用了FunHPC-AI宝箱-ComfyUI-Plus,使用了dreamshaperXL全能模型,生成了几张国风图,效果真的让人惊叹!

最近试用了FunHPC-AI宝箱-ComfyUI-Plus&#xff0c;使用了dreamshaperXL全能模型&#xff0c;生成了几张国风图&#xff0c;效果真的让人惊叹&#xff01;&#x1f338; https://www.funhpc.com/#/ 通过简单的提示词&#xff0c;我就能轻松生成出充满古韵的图像&#xff1a;汉服…

linux查看外网ipv4地址

在Linux系统中&#xff0c;可以使用以下几种方法来查看外网IPv4地址&#xff0c;并确保强制使用IPv4。 前言 特别感谢浪浪云对本文的大力支持。浪浪云作为领先的云计算服务提供商&#xff0c;凭借其卓越的性能和可靠性&#xff0c;帮助无数企业和开发者实现了业务的快速部署和…

苹果宣布iOS 18正式版9月17日推送:支持27款iPhone升级

9月10日消息&#xff0c;在苹果秋季发布会结束后&#xff0c; 苹果宣布将于9月17日(下周二)推送iOS 18正式版系统。 苹果官网显示&#xff0c;iOS 18正式版将兼容第二代iPhone SE及之后的所有机型&#xff0c;加上刚发布的iPhone 16系列&#xff0c;共兼容27款iPhone。 iOS 18升…

为拖延症量身定制的AI工具,让Kimi做我的《每日信息整理助手》

AI不止对传统行业带来巨大的改变&#xff0c;对日常生活也便利了不少&#xff0c;现在这个时代获取信息的方式太简单了。 我们每天都会接受大量的信息&#xff0c;难免一天下来会忘记很多事情&#xff0c;有时候突然想起了一个点子&#xff0c;有时候突然有一件急事、一件待办事…

基于SpringBoot+Vue的校园失物招领系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 【2025最新】基于JavaSpringBootVueMySQL的校园失物…

2024年黑龙江事业单位考试报名保姆级流程

黑龙江事业编考试报名须知 一、报名安排 1.报名时间&#xff1a;9月18日9&#xff1a;00-9月24日17&#xff1a;00 2.报名网址&#xff1a;黑龙江省事业单位公开招聘服务平台 二、报名操作流程 本次招考采取网上报名的方式。 1.网上报名。应聘人员可于2024年9月18日9&…

企业数字化转型、建设和升级面临的主要难题和解决之道(2)

用爱编程30年&#xff0c;倾心打造工业和智能智造软件研发平台SCIOT,用创新的方案、大幅的让利和极致的营销&#xff0c;致力于为10000家的中小企业实现数字化转型&#xff0c;打造数字化企业和智能工厂&#xff0c;点击上边蓝色字体&#xff0c;关注“AI智造AI编程”或文末扫码…

总结拓展九:SAP数据迁移(1)

第一节&#xff1a;数据迁移介绍 1、SAP上线前MM模块需要迁移的数据 1.1 静态数据&#xff1a;物料主数据、供应商主数据等&#xff1b; 1.2 业务数据&#xff1a;采购订单&#xff08;未收货&#xff09;、发票校验&#xff08;未校验&#xff09;、采购信息记录、货源清单…

如何使用python运行Flask开发框架并实现无公网IP远程访问

文章目录 1. 安装部署Flask2. 安装Cpolar内网穿透3. 配置Flask的web界面公网访问地址4. 公网远程访问Flask的web界面 本篇文章主要讲解如何在本地安装Flask&#xff0c;以及如何将其web界面发布到公网进行远程访问。 Flask是目前十分流行的web框架&#xff0c;采用Python编程语…

【数据结构与算法 | 灵神题单 | 快慢指针(链表)篇】力扣876, 2095, 234

1. 力扣876&#xff1a;链表的中间节点 1.1 题目&#xff1a; 给你单链表的头结点 head &#xff0c;请你找出并返回链表的中间结点。 如果有两个中间结点&#xff0c;则返回第二个中间结点。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5] 输出&#xff1a;[3,4,…

pdf删除一页怎么删除?5种方法详细讲解,pdf删除页面实用技巧分享!

pdf删除一页怎么删除&#xff1f;从pdf文档中删除某页是一项非常实用的技术&#xff0c;特别是在需要编辑pdf文件时。在某些情况下&#xff0c;您可能需要删除页面以保护机密信息、去除不必要的内容&#xff0c;或者为了压缩pdf文件的大小。因此&#xff0c;掌握有效且简单的删…

搭建线上扭蛋机小程序,企业新的盈利模式?

近几年&#xff0c;随着市场对潮玩商品的需求不断增加&#xff0c;越来越多的资本入局到潮玩市场&#xff0c;因此&#xff0c;扭蛋机也开始在市场中持续走红&#xff0c;扭蛋机的各种创新玩法&#xff0c;也刺激着消费者的购买欲望&#xff0c;推动市场的发展。 扭蛋机的目标…

Java面试题下

Java面试题下 异常 Exception和Error有什么区别 所有的异常都有一个共同的祖先Throwable类。有两者子类: Exception:程序可以本身处理的异常&#xff0c;可通过catch来捕获。Exception 又可以分为 Checked Exception (受检查异常&#xff0c;必须处理) 和 Unchecked Excepti…

chapter14-集合——(List-HMap)——day18

目录 536-HMap阶段小结 537-HMAp底层机制 538-HMAP源码解读 539-HMap扩容树化触发 重点在于hashmap的扩容机制 它内部是k-v对方式存储数据&#xff0c;Hash$node类型&#xff1b;相同的key&#xff0c;就会覆盖 Hash$node类型实现了mapentry接口 扩容条件&#xff0c;看是否…

【在Linux世界中追寻伟大的One Piece】五种IO模型和阻塞IO

目录 1 -> 五种IO模型 1.1 -> 阻塞IO(Blocking IO) 1.2 -> 非阻塞IO(Non-blocking IO) 1.3 -> 信号驱动IO(Signal-Driven IO) 1.4 -> IO多路转接(IO Multiplexing) 1.5 -> 异步IO(Asynchronous IO) 2 -> 高级IO概念 2.1 -> 同步通信VS异步通信…

鸿蒙介绍、鸿蒙编程环境、基本组件、页面跳转学习

系列文章目录 第一章 鸿蒙介绍、鸿蒙编程环境、基本组件、页面跳转学习 文章目录 系列文章目录前言一、HarmonyOS基础1. 鸿蒙系统是什么&#xff1f;2. 鸿蒙系统的重要目录及文件 二、HarmonyOS编程介绍1. ArkTS编程语言介绍2. DevEco Studio编程环境介绍3. 关系介绍 三、使用…

ButterKnife:Android视图绑定的简化专家

在Android应用开发中&#xff0c;与UI组件的交互是不可或缺的一部分。然而&#xff0c;传统的视图绑定方式往往涉及大量的样板代码&#xff0c;这不仅增加了代码的复杂性&#xff0c;也使得维护变得更加困难。为了解决这一问题&#xff0c;Jake Wharton推出了ButterKnife&#…

【鸿蒙】HarmonyOS NEXT星河入门到实战2-ArkTS快速入门

目录 一、ArkTS基础快速入门 二、认识和存储数据 2.1 认识数据 2.2 存储数据&#xff08;变量、常量&#xff09; 2.2.1 变量 2.2.2 常量&#xff08;不可修改&#xff09; 三、数组 四、函数-Function 4.1 函数的基本使用 4.1.1 定义函数 4.1.2 调用函数 4.2 函数…

leetcode 2576.求出最多标记下标

2576.求出最多标记下标 题意&#xff1a; 解析&#xff1a; 数组长为 n n n&#xff0c;因为一次标记两个&#xff0c;所以数组中最多有 ⌊ n 2 ⌋ \lfloor \frac{n}{2}\rfloor ⌊2n​⌋ 对标记。 贪心的考虑&#xff0c;一个数 x 一定优先与满足 y ≥ 2 x y \ge 2x y≥2…

驱动(RK3588S)第十一课时:linux内核定时器和poll轮询

目录 学习目标一、内核的定时器1、定时器概念2、定时器的作用与分类3、定时器API函数1、初始化定时器核心结构体2、定时器核心结构体3、向内核注册定时器资源用于激活定时器4、删除定时器的资源5、这是改变定时器时间的函数&#xff0c;如果在指定的定时器(timer)没超时前调用&…