给shared_ptr添加自定义删除器的几种方式

四、c++11智能指针之shared_ptr实现:自定义删除器 private ://指向计数器的指针 T * m_ptr;//多个智能指针对象共享一个引用计数,因此要定义为指针 size_t * m_size;//数组大小 std : : mutex * m_mutex;// 互斥锁,定义为指针类型,仅仅用来保护引用计数器 public ://构造 mySharedSp(const mySharedSp < T > & other); 阅读详情
AI摘要

本文详细介绍了如何将自定义删除器传递给C++中的shared_ptr,包括使用普通函数、仿函数、lambda表达式及std::default_delete的方式,并展示了如何避免内存泄漏,确保数组元素正确析构。

将回调函数传递给 shared_ptr 的构造函数,该构造函数将从其析构函数中调用以进行删除

方式一、使用普通函数

// 自定义删除器
void deleter(Sample * x)
{
	std::cout << "Deleter function called" << std::endl;
	delete[] x;
}
// 构造函数传递自定义删除器指针
std::shared_ptr<Sample> p1(new Sample[5], deleter);

方式二、使用仿函数

class Deleter
{
public:
	void operator() (Sample *x) {
		std::cout << "Deleter function called" << std::endl;
		delete[] x;
	}
};
// 构造函数传递自定义删除器指针
std::shared_ptr<Sample> p2(new Sample[5], Deleter);

方式三、使用lambda表达式

std::shared_ptr<Sample> p3(new Sample[5], [](Sample *x) {
	std::cout << "Deleter function called" << std::endl;
	delete[] x;
});

方式四、使用std::default_delete

std::shared_ptr<Sample> p(new Sample[5], std::default_delete<Sample[]>());

举例:

#include <iostream>
#include <memory>

class Sample {
public:
	Sample() {
		std::cout << "Sample Constructor" << std::endl;
	}
	~Sample() {
		std::cout << "~Sample Destrutor" << std::endl;
	}
};

void deleter(Sample *x)
{
	std::cout << "Deleter function called" << std::endl;
	delete[] x;
}

class Deleter
{
public:
	void operator() (Sample *x) {
		std::cout << "Deleter function called" << std::endl;
		delete[] x;
	}
};

int main()
{
	{
		std::shared_ptr<Sample> p0(new Sample[5]);
		//std::shared_ptr<Sample> p1(new Sample[5], deleter);		//方式一
		//std::shared_ptr<Sample> p2(new Sample[5], Deleter());		//方式二
		//std::shared_ptr<Sample> p3(new Sample[5], [](Sample *x) {  //方式三
		//	std::cout << "Deleter function called" << std::endl;
		//	delete[] x;
		//});
		//std::shared_ptr<Sample> p(new Sample[5], std::default_delete<Sample[]>()); //方式四
	}
	
	getchar();
	return 0;
}

运行结果:

Sample Constructor
Sample Constructor
Sample Constructor
Sample Constructor
Sample Constructor
~Sample Destrutor

只看到一个析构函数,这时候已经发生了内存泄露,数组中的5个对象,只有一个发生了析构。

int main()
{
	{
		std::shared_ptr<Sample> p1(new Sample[5], deleter);		//方式一
	}
	
	getchar();
	return 0;
}

此时的运行结果:

Sample Constructor
Sample Constructor
Sample Constructor
Sample Constructor
Sample Constructor
Deleter function called
~Sample Destrutor
~Sample Destrutor
~Sample Destrutor
~Sample Destrutor
~Sample Destrutor

发现p1析构时候,会自动调用deleter(你构造的时候传进去的),对数组中的所有元素一一进行删除。此时没有内存泄露。

修改为这样也是一样的结果,只是调用的的Deleter中的operator() (Sample *x)函数

std::shared_ptr<Sample> p2(new Sample[5], Deleter());		//方式二

采用lambda函数的时候,就是:

std::shared_ptr<Sample> p3(new Sample[5], [](Sample *x) {  //方式三
			std::cout << "Deleter function called" << std::endl;
			delete[] x;
		});

使用std::default_delete作为删除器,default_delete的内部是通过调用delete来说实现功能的。

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

也可以写成

std::shared_ptr<int> p(new int[5], std::default_delete<int[]>());

封装一个make_shared_array方法来让shared_ptr支持数组

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

测试代码:

std::shared_ptr<Sample> p5 = make_shared_array<Sample>(5);
std::shared_ptr<int> p5 = make_shared_array<int>(5);

参考:
C++ 智能指针 shared_ptr 详解与示例
std::default_delete官方文档和实例
智能指针拾遗

shared_ptr的详解 参考:《C++ primer 第五版》                https://www.cnblogs.com/boydfd/p/5146432.html (需要多看几遍)前言程序中常用的存储形式如下。静态内存:static对象,类static的数据成员,函数外的变量。栈内存:函数内的非static对象。自由空间或堆:动态分配的对象,程序控制生命周期。动态内存与智能指针从前,我们使用运算符n... 阅读详情

相关推荐

极空间NAS零基础部署Wiki.js:Docker+PostgreSQL全流程避坑指南

本文提供了一份在极空间NAS上从零部署Wiki.js私有知识库的详细指南。通过Docker容器化技术,结合PostgreSQL数据库,手把手讲解环境准备、核心组件配置、性能优化及安全加固等全流程,并特别针对极空间平台特性提供了避坑要点,帮助用户打造安全、高效、自主可控的知识管理系统。

3a9bq4r8t2y的博客 483

c++11智能指针(二):shared_ptr和自定义的Deleter

本节讨论怎样使用 std::shared_ptr自定义Deleter.当一个shared_ptr对象超出作用域时,其析构函数被调用,在析构函数中,将其引用计数减1,如果引用计数的值变为0,则删除关联的原始指针。要删除析构函数中的内部原始指针,默认情况下,shared_ptr调用delete()函数,即delete Pointer;但是,我们在析构函数中并不总是要使用delete函数,还可能有其他的...

小麒麟的成长之路 1万+

​开源大模型实战:GLM-4.1V-Thinking本地部署教程(附API调用代码)

​在AI应用从“能用”向“好用”进阶的当下,​的需求愈发强烈:企业需保障数据安全(如医疗影像、金融报告不外传),开发者追求定制化能力(如微调模型适配垂直场景),科研团队则依赖离线环境处理敏感数据。智谱AI开源的​(10B级参数,支持图像、视频、文档多模态推理)凭借的优势,成为本地部署的热门选择。不过,对于“不想折腾技术”的普通用户或快速验证需求的团队而言,​,无需安装配置,打开即用,堪称“零门槛”体验的捷径。本文将分为两部分:先手把手教你​(适合有技术背景的用户),再对比介绍。

gogoMark的博客 1339

std::shared_ptr 中deleter 的内存模型、调用逻辑

template <class _Ux, class _Dx, enable_if_t<conjunction_v<is_move_constructible<_Dx>, _Can_call_function_object<_Dx&, _Ux*&>, _SP_conve...

商少 752

秦时明月6.2魔改版_从零到一部署指南_含安卓客户端配置与GM后台直通

本文详细介绍了秦时明月6.2魔改版的从零到一部署指南,包括环境准备、服务端安装、安卓客户端配置以及GM后台直通等关键步骤。特别针对安卓客户端配置和GM工具使用提供了实用技巧,帮助用户快速搭建并优化游戏服务器,确保稳定运行。

weixin_42522964的博客 315

【MeshLib & VTK】MeshLib PK VTK

本文分享三维几何处理库MeshLib,并将其与VTK进行对比,希望对各位小伙伴有所帮助!

qq_40041064的博客 1070

智能指针shared_ptr:自定义删除器

2.智能指针创建的时候,第二个参数是自定义删除器,默认情况下,shared_ptr调用delete()函数。如果要保住这个变量,需要对构造智能指针的时候进行处理。(调用智能指针的第二个参数进行处理)1.普通指针转化成智能指针。

qq_38409301的博客 920

11. 使用 HTTP PUT, PATCH 以及 MERGE 请求消费 SAP ABAP OData 服务修改操作的实现及其区别

使用 SAP ABAP SEGW 事物码实现 OData 服务的修改操作时,对于消费端通过 PATCH/MERGE 和 PUT 这三种不同类型的 HTTP 请求触发的场景,我们应该在 UPDATE_ENTITY 方法里用 IF 分支分别进行处理,原因就在于 GET_ENTITY 方法是否在修改处理逻辑的过程中被触发。......

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 2448

std::shared_ptr之deleter的巧妙应用

本文由作者邹启文授权网易云社区发布。std::shared_ptr一次创建,多处共享,通过引用计数控制生命周期。 实例 在邮箱大师PC版中,我们在实现搜索时,大致思路是这样的: 每一个账号都有一个SearchFlow,搜索开始后,所有SearchFlow一起并发搜索, 当全部SearchFlow通过callback返回后,意味着搜索结束。 方案: 搜索前,使用std::set&lt;int64_t...

Neteasecloud的博客 498

【100分】【等和子数组最小和】

逆序排序,这样能够使得在分组时优先选取较大的元素,以便将元素分配到较小的子集中,从而使得每个子集的和相对均衡。给定一个数组nums,将元素分为若干个组,使得每组和相等,求出满足条件的所有分组中,组内元素和的最小值。分成若干个组,使得每组的和相等,并求出满足条件的所有分组中,组内元素和的最小值。在递归的过程中,我们需要注意一个优化点,即避免将相同和的桶重复计算。4 个子集(5),(1,4),(2,3),(2,3)2 个子集(5, 1, 4),(2,3, 2,3)个子集,则返回子集和的最小值,如果不能,则将。

weixin_54707168的博客 1167

multisim14.3无法访问数据库...如何解决?

🏆本文收录于 《全栈 Bug 调优(实战版)》 专栏。专栏聚焦真实项目中的各类疑难 Bug,从成因剖析 → 排查路径 → 解决方案 → 预防优化全链路拆解,形成一套可复用、可沉淀的实战知识体系。无论你是初入职场的开发者,还是负责复杂项目的资深工程师,都可以在这里构建一套属于自己的「问题诊断与性能调优」方法论,助你稳步进阶、放大技术价值 。

**My Coding Family** 4434

C++ 智能指针shared_ptr/unique_ptr自定义删除器

默认情况下,智能指针使用delete释放其管理的资源,有时候,可能要修改默认使用delete释放资源的行为。本文将列出我所知道的所有自定义删除器的方法。 目录零、引例一、使用函数二、使用可调用类三、使用lambda表达式四、使用std::function 零、引例 Connection是一个管理连接类,在释放Connection之前,我们需要调用close函数来关闭连接。观察如下代码: #incl...

Marvek的博客 1万+

合肥工业大学嵌入式系统原理实验报告

GPKDAT 的6、7引脚设置低电平,设置GPKDAT = 0x30则34灯亮12灯灭,GPKDAT 的4、5、6、7引脚全为高电平,设置GPKDAT = 0xf0,则led灯全灭。注意在烧写时要连接主机后面的USB接口,烧写完成后,要关闭开发板电源,将S2拨动开关置于NAND位置,然后重新开启开发板电源, 则开发板运行刚刚烧入的裸机程序。实验修改要求:在延时不变的条件下,将原程序中四个LED全亮,然后全灭的显示状态,修改为“四个全亮,然后1和2亮(3和4灭),然后3和4亮(1和2灭),最后全灭”。

Martin-share的博客 3097

【C++】shared_ptr共享型智能指针详解

指针是C/C++区别于其他语言的最强大的语法特性,借助指针,C/C++可以直接操纵内存内容。但是,指针的引入也带来了一些使用上的困难,这要求程序员自己必须手动地对分配申请的内存区进行管理。 本文实例源码github地址:https://github.com/yngzMiao/yngzmiao-blogs/tree/master/2020Q2/20200427。 shared_ptr基本用法 智能...

Yngz_Miao的博客 3万+

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

shared_ptr常用操作、计数、自定义删除器 [转]

https://blog.youkuaiyun.com/u012278016/article/details/108187828

baidu_41388533的博客 2000

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

智能指针shared_ptr中new和make_ptr两种方式的区别

shared_ptr是c++11中的智能指针,其可以自动的释放指针,避免了new之后忘记delete的问题。 shared_ptr 对象在内部指向两个内存位置: 1、指向对象的指针。 2、用于控制引用计数数据的指针。 计数数据指针的作用: 1、当新的 shared_ptr 对象与指针关联时,使用use_count(),其指针关联的引用计数增加1。 2、当任何 shared_ptr 对象超出作...

misterdo的专栏 9253

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

C++:shared_ptr简介以及常见问题

本文中的shared_ptr以vs2010中的std::tr1::shared_ptr作为研究对象。可能和boost中的有些许差异,特此说明。 基本功能 shared_ptr提供了一个管理内存的简单有效的方法。shared_ptr能在以下方面给开发提供便利: 1、 使用shared_ptr能有效的解决忘记释放内存带来的内存泄漏问题。同时通过自定义删除器功能还能广泛的用于任何需要”释放”的资源...

smartDMer的专栏 1万+

C++智能指针 shared_ptr 和 unique_ptr

传统C/C++编程中,使用new或者malloc动态申请内存后,必须手动调用delete或者free去释放,否则就会造成内存泄漏。在C++ 11语法中,提供了智能指针来管理内存,开发者不必再关心内存的释放问题,智能指针可以自动去释放管理的内存空间。

new9232的博客 1459

shared_ptr指定删除器

通过 的自定义删除器(deleter) 实现连接的自动归还: 的默认删除器是 ,但这里通过 lambda 表达式定义了自定义删除器:当返回的 超出作用域(即上层代码使用完连接)时,删除器不会销毁连接,而是将其归还给连接池。连接被归还给队列后不会重新进行完整初始化,而是保持 “就绪状态” 等待下一次复用,仅在必要时进行轻量级的状态重置或有效性校验。这种设计是连接池提升性能的核心原因之一。上述代码使用了shred_ptr带自定义删除器的构造函数,原型如下: 代码中正是使用了这个构造函数: 详细

m0_58063650的博客 611

浅析shared_ptr 和weak_ptr、定制删除器

shared_ptr的作用如同指针,但又比指针更加安全,甚至还能提供基本的线程安全保证。记录了有多少个shared_ptrs共同指向一个对象(即引用计数),它基本上解决了在使用c++开发过程中不可避免的使用指针而遇到的许多问题,例如:内存泄漏和内存的提前释放,还有由于指针内存申请而产生的异常问题等。shared_ptr指针解决了auto_ptr和一旦最后一个这样的指针被销毁,也就是一旦某个对象的引

wangpengcsdn1的博客 4557

5.3c++:shared_ptr的常用操作、计数、自定义删除器等(转载)

shared_ptr 引用计数的增加和减少 共享式:引用计数,每一个 shared_ptr的拷贝都指向相同的内存(对象),只有最后一个指向该对象的shared_ptr指针不需要再指向该对象的时候,才会析构对象。 1.1引用计数的增加 每个shared_ptr都会记录有多少个其他的shared_ptr指向相同的对象 auto p6 = make_shared<int> ...

qq_41543888的博客 4050

Cpp / shared_ptr 配置删除器的方法

一、普通函数 void Deleter(T *x) { delete[] x; } std::shared_ptr<T> p1(new T[5], Deleter); 二、仿函数 class Deleter { public: void operator() (T *x) { delete[] x; } }; std::shared_ptr<T> p2(new T[5], Deleter); 三、lamda 表达式 std::shared_ptr&lt

布袋和尚 939

shared_ptr定制删除器

定制删除器 shared_ptr的另一种形式的构造函数share_prt(Y* p, D d), 参见boost shared_ptr基本用法介绍它的第一个参数是要被管理的指针,而第二个删除器参数d则告诉shared_ptr在析构时不是使用delete来操作指针p,而是要用d来操作,即把delete p 换成 d (p)。 在这里d可以是一个函数对象,也可以说一个函数指针,只要它能够像函数那样被调用,使得d ( p )成立即可。对删除器的要求是它必须可以拷贝,行为也必须也像delete那样,不能抛出异常。

weixin_41176628的博客 965

一篇文章说清楚shared_ptr,unique_ptr的区别和关系

一. shared_ptr的基本用法 (一)与unique_ptr的比较 比较 shared_ptr unique_ptr 备注 初始化 ①shared_ptr<T> sp; sp.reset(new T()); ②shared_ptr<T> sp(new T()); ③shared_ptr<T> sp1 = sp;//拷贝...

肖邦的夜曲的专栏 1万+

shared_ptr之循环引用&定置删除器

shared_ptr虽然方便,但是它有着一个致命的缺陷就是循环引用问题,因为shared_ptr本身并没有能力解决这个问题,所以我们又引入了弱指针weak_ptr来辅助shared_ptr解决这个问题。 那么循环引用又是什么场景? 举个栗子: 假设现在我们要创建一个双向整形链表,但是这个链表的指针域全部都用shared_ptr维护: struct Node {     int

Sunnylunch-blog 2828

shared_ptr与weak_ptr

本文主要分析了C++中的shared_ptr和weak_ptr智能指针的工作原理及实现机制。shared_ptr采用引用计数管理对象生命周期,支持自定义删除器,但需注意避免循环引用和多指针管理同一裸指针等问题。weak_ptr作为shared_ptr的观察者,不参与引用计数,主要用于解决循环引用和观察对象状态。文章深入剖析了控制块基类sp_count_base的架构,包括引用计数管理、对象释放逻辑等核心机制,并介绍了自定义删除器sp_count_deleter的实现方式。通过源码分析,揭示了智能指针如何通过

m0_47175840的博客 818
上一篇: C++11 基于范围的for循环
下一篇: std::make_shared的误用造成的内存泄露
hp_cpp
博客等级 码龄11年 310粉丝 218原创
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值