0

0

怎样用智能指针实现对象池 使用shared_ptr定制删除器实现资源复用

P粉602998670

P粉602998670

发布时间:2025-08-01 10:18:02

|

957人浏览过

|

来源于php中文网

原创

对象池的核心目标是复用资源,减少频繁创建和销毁的开销。1. 通过定制删除器,shared_ptr 在引用计数归零时不释放内存而是将对象放回池中;2. 对象池结构包含存储容器、删除器、获取和释放方法;3. 需注意避免裸指针误删、线程安全、池大小限制及构造参数支持等细节;4. 实现方式兼顾安全与性能,适合高频场景但需处理状态重置和并发问题。

怎样用智能指针实现对象池 使用shared_ptr定制删除器实现资源复用

对象池的核心目标是复用资源,减少频繁创建和销毁的开销。用 C++ 的 shared_ptr 实现对象池时,关键在于定制删除器:当引用计数归零时,不是直接释放内存,而是把对象“放回池中”。

怎样用智能指针实现对象池 使用shared_ptr定制删除器实现资源复用

为什么需要定制删除器?

默认情况下,shared_ptr 在最后一个引用失效时会调用 delete。但对象池希望这个对象不被真正删除,而是回收到池里等待下次使用。

怎样用智能指针实现对象池 使用shared_ptr定制删除器实现资源复用

这时候就需要一个自定义的删除器函数(或仿函数),告诉 shared_ptr

“别删了它,把它还给我。”

这样就能控制对象生命周期,实现复用。


如何设计对象池结构?

一个简单的对象池可以包含以下几个部分:

  • 存储可用对象的容器(如 std::stack
  • 定制删除器函数
  • 获取和释放对象的方法

举个例子:

template 
class ObjectPool {
public:
    using Deleter = std::function;

    // 池内回收对象的删除器
    static void returnToPool(T* ptr) {
        instance()._pool.push(ptr);
    }

    // 获取一个对象,如果池里有就复用,没有就新建
    shared_ptr get() {
        if (_pool.empty()) {
            return shared_ptr(new T, returnToPool);
        } else {
            T* obj = _pool.top();
            _pool.pop();
            return shared_ptr(obj, returnToPool);
        }
    }

private:
    std::stack _pool;
    static ObjectPool& instance() {
        static ObjectPool pool;
        return pool;
    }
};

这种方式让每次获取的对象都带上了“回收逻辑”,只要没人用了,就会自动回到池里。

Cutout.Pro
Cutout.Pro

AI驱动的视觉设计平台

下载

使用时需要注意哪些细节?

  1. 避免裸指针误删

    • 不要对外暴露原始指针,只返回 shared_ptr,否则用户可能手动 delete 导致崩溃。
  2. 线程安全问题

    • 如果多个线程同时访问对象池,stackshared_ptr 的操作都需要加锁。
    • 可以在 get() 和删除器中加互斥锁保护 _pool 的访问。
  3. 池的大小限制

    • 可以设置最大容量,超过上限再释放内存,而不是无限制增长。
    • 也可以定期清理空闲对象,节省资源。
  4. 构造参数支持

    • 上面的例子只能默认构造对象,若想传递参数,可以用工厂方法封装 new T(...)

这样做有什么好处和限制?

优点:

  • 管理方便:靠智能指针自动触发回收逻辑,不用手动跟踪谁在用哪个对象。
  • 性能提升:减少动态分配次数,适合高频创建销毁的场景,比如网络连接、数据库连接等。

缺点:

  • 实现复杂一些,特别是要考虑线程安全。
  • 对象状态不清空,复用前需要重置,否则可能出现残留数据影响新用途。

基本上就这些。用 shared_ptr 加定制删除器来实现对象池,是一种兼顾安全和性能的做法,虽然细节上要注意点,但一旦搭好,后续使用很省心。

相关专题

更多
线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

476

2023.08.10

数据库Delete用法
数据库Delete用法

数据库Delete用法:1、删除单条记录;2、删除多条记录;3、删除所有记录;4、删除特定条件的记录。更多关于数据库Delete的内容,大家可以访问下面的文章。

268

2023.11.13

drop和delete的区别
drop和delete的区别

drop和delete的区别:1、功能与用途;2、操作对象;3、可逆性;4、空间释放;5、执行速度与效率;6、与其他命令的交互;7、影响的持久性;8、语法和执行;9、触发器与约束;10、事务处理。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

208

2023.12.29

数据库三范式
数据库三范式

数据库三范式是一种设计规范,用于规范化关系型数据库中的数据结构,它通过消除冗余数据、提高数据库性能和数据一致性,提供了一种有效的数据库设计方法。本专题提供数据库三范式相关的文章、下载和课程。

340

2023.06.29

如何删除数据库
如何删除数据库

删除数据库是指在MySQL中完全移除一个数据库及其所包含的所有数据和结构,作用包括:1、释放存储空间;2、确保数据的安全性;3、提高数据库的整体性能,加速查询和操作的执行速度。尽管删除数据库具有一些好处,但在执行任何删除操作之前,务必谨慎操作,并备份重要的数据。删除数据库将永久性地删除所有相关数据和结构,无法回滚。

2071

2023.08.14

vb怎么连接数据库
vb怎么连接数据库

在VB中,连接数据库通常使用ADO(ActiveX 数据对象)或 DAO(Data Access Objects)这两个技术来实现:1、引入ADO库;2、创建ADO连接对象;3、配置连接字符串;4、打开连接;5、执行SQL语句;6、处理查询结果;7、关闭连接即可。

346

2023.08.31

MySQL恢复数据库
MySQL恢复数据库

MySQL恢复数据库的方法有使用物理备份恢复、使用逻辑备份恢复、使用二进制日志恢复和使用数据库复制进行恢复等。本专题为大家提供MySQL数据库相关的文章、下载、课程内容,供大家免费下载体验。

253

2023.09.05

vb中怎么连接access数据库
vb中怎么连接access数据库

vb中连接access数据库的步骤包括引用必要的命名空间、创建连接字符串、创建连接对象、打开连接、执行SQL语句和关闭连接。本专题为大家提供连接access数据库相关的文章、下载、课程内容,供大家免费下载体验。

322

2023.10.09

漫蛙2入口地址合集
漫蛙2入口地址合集

本专题整合了漫蛙2入口汇总,阅读专题下面的文章了解更多详细内容。

13

2026.01.06

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PostgreSQL 教程
PostgreSQL 教程

共48课时 | 6.7万人学习

MongoDB 教程
MongoDB 教程

共17课时 | 1.8万人学习

C# 教程
C# 教程

共94课时 | 6.1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号