当前位置: 首页 > web >正文

new/delete 重载与对象池实现

C++ 内存管理笔记:new/delete 重载与对象池实现

一、new/delete 基础概念

1. malloc 与 new 的区别

  • 内存分配方式
    • malloc 按字节分配内存,返回 void* 类型
    • new 根据类型分配内存,如 new int[10] 返回 int*
  • 初始化功能
    • malloc 仅分配内存
    • new 分配内存后调用构造函数初始化对象
  • 错误处理
    • malloc 失败返回 nullptr
    • new 失败抛出 bad_alloc 异常

2. free 与 delete 的区别

  • delete 先调用对象析构函数,再释放内存
  • delete[] 用于释放数组内存,会逐个调用数组元素的析构函数
二、new/delete 重载实现

全局重载示例

// 单个对象内存分配
void* operator new(size_t size) {void* p = malloc(size);if (!p) throw bad_alloc();cout << "operator new addr:" << p << endl;return p;
}// 单个对象内存释放
void operator delete(void* ptr) {cout << "operator delete addr:" << ptr << endl;free(ptr);
}// 数组内存分配
void* operator new[](size_t size) {void* p = malloc(size);if (!p) throw bad_alloc();cout << "operator new[] addr:" << p << endl;return p;
}// 数组内存释放
void operator delete[](void* ptr) {cout << "operator delete[] addr:" << ptr << endl;free(ptr);
}
三、自定义类内存管理

示例类 Test

class Test {
public:Test(int data = 10) : ptr(new int(data)) { cout << "Test()" << endl; }~Test() { delete ptr;cout << "~Test()" << endl; }
private:int* ptr;
};

内存分配与释放测试

// 正确使用方式
Test* p1 = new Test();  // 调用构造函数
delete p1;              // 调用析构函数// 错误示例(勿混用)
Test* p2 = new Test[5];
delete p2;              // 仅释放首元素,内存泄漏!
delete[] p2;            // 正确释放数组
四、对象池实现原理

核心思想

  • 预分配大块内存,避免频繁调用 malloc/free
  • 通过内存复用提高性能

模板类 Queue 实现对象池

template<typename T>
class Queue {
private:struct QueueItem {QueueItem(T data = T()) : _data(data), _next(nullptr) {}// 对象池内存管理void* operator new(size_t size) {if (_itemPool == nullptr) {// 创建对象池_itemPool = (QueueItem*)new char[POOL_ITEM_SIZE * sizeof(QueueItem)];QueueItem* p = _itemPool;for (; p < _itemPool + POOL_ITEM_SIZE; p++) {p->_next = p + 1;  // 构建链表}p->_next = nullptr;}QueueItem* p = _itemPool;_itemPool = _itemPool->_next;  // 从池中取出对象return p;}void operator delete(void* ptr) {QueueItem* p = (QueueItem*)ptr;p->_next = _itemPool;  // 将对象放回池中_itemPool = p;}T _data;QueueItem* _next;static QueueItem* _itemPool;static const int POOL_ITEM_SIZE = 100000;};QueueItem* _front;  // 队头指针QueueItem* _rear;   // 队尾指针
};// 静态成员初始化
template<typename T>
typename Queue<T>::QueueItem* Queue<T>::QueueItem::_itemPool = nullptr;
五、对象池性能测试
int main() {Queue<int> que;for (int i = 0; i < 1000000; i++) {que.push(i);  // 使用对象池分配内存que.pop();    // 归还内存到对象池}cout << que.empty() << endl;return 0;
}
六、关键要点总结
  1. 内存泄漏检测
    • 可通过重载 new/delete 记录内存分配情况
    • 建立全局映射表跟踪未释放的内存
  2. 混用风险
    • 对有析构函数的类,newdeletenew[]delete[] 必须配对使用
    • 内置类型无析构函数,混用不会导致内存泄漏
  3. 对象池优势
    • 减少系统调用开销,提高内存分配效率
    • 适合频繁创建和销毁对象的场景
  4. 内存管理最佳实践
    • 优先使用智能指针(如 std::unique_ptrstd::shared_ptr
    • 仅在性能敏感场景手动管理内存
    • 始终保持 new/delete 操作符使用一致性
http://www.xdnf.cn/news/2291.html

相关文章:

  • 高性能电脑系统优化工具Advanced SystemCare PRO v18.3.0.240 解锁永久专业版
  • 学习Spire.Office for Java版本的科学实践
  • 栈与队列 Part 2
  • 【NeurlPS 2024】MAR:无矢量量化的自回归图像生成
  • Jquery -函数调用使用创建立即执行函数
  • 代码随想录回文子序列
  • MQL5教程 06 EA开发实战
  • 【免费项目分享】(项目加说明文档)基于Go语言的城市电动汽车充电桩管理系统设计与实现
  • 深度学习原理与Pytorch实战
  • B. And It‘s Non-Zero
  • 八、Constants(常量)
  • Spring 学习笔记之 @Transactinal实现原理
  • Loki日志体系的搭建
  • Linux: 如何在VMware上安装Ubuntu操作系统
  • Redis 数据类型全览:特性、场景与操作实例
  • 泽润新能IPO隐忧:募资缩水2亿元,毛利率两连降,内控存瑕疵?
  • Eigen稀疏矩阵类 (SparseMatrix)
  • VS2019 与gitcode团队管理
  • QT6 源(52)篇二:存储 c 语言字符串的类 QByteArray 的使用举例,
  • Git基本操作
  • 第34课 常用快捷操作——按“空格键”旋转图元
  • MySQL技术白皮书
  • 定位与解决线上 OOM 问题:原因分析与快速排查指南
  • o4 - mini 助力,OpenAI 向免费用户推出轻量版 Deep Research
  • CMake 中使用动态库时的 DLL 拷贝逻辑详解(以 zlib 为例)
  • 【BBDM】main.py -- notes
  • 传统智慧焕新,打造现代养生生活
  • X86物理机安装iStoreOS软路由
  • ShaderToy学习笔记 01.基础知识
  • C++学习:六个月从基础到就业——模板编程:函数模板