C++拾遗--new delete 重载

来源:互联网 发布:黑莓9930安装软件 编辑:程序博客网 时间:2024/06/06 20:11

                        C++拾遗--new delete 重载

前言

    new和delete是操作动态内存的一对操作。对它们重载可以对内存管理进行有效的定制。

正文

1.局部重载

特别针对某一类型,对new和delete进行重载,可以对该类型对象的动态创建实行监控。如下代码:

代码

#include <iostream>using namespace std;class MyClass{public:MyClass(){cout << "MyClass()" << endl;}~MyClass(){cout << "~MyClass()" << endl;}void *operator new(std::size_t size){cout << "局部new call" << endl;void *mem = malloc(size);    if (mem)     //内存分配失败,则返回0return mem; //return malloc(size);elsethrow bad_alloc();     //内存分配失败,抛出异常}void operator delete(void *ptr){cout << "局部delete call" << endl;//不为空,则调用free释放内存if (ptr){free(ptr);}}};int main(){cout << "******局部new delete重载演示***by David***" << endl;MyClass *my = new MyClass;delete my;cin.get();return 0;}
运行



运行结果表明

表达式new整合了内存分配和构造函数。先调用malloc分配内存,然后调用指定类型并相匹配的构造函数初始化该段内存。

表达式delete整合了析构函数和内存释放。先调用类的析构函数释放资源,后调用free释放分配的内存。


代码二

下面一个例子提供了对内存分配进行监控的一种方法。

#include <iostream>using namespace std;class MyClass{public://count记录未释放的对象个数static int count;int a;MyClass(){cout << "MyClass()" << endl;count++;}~MyClass(){cout << "~MyClass()" << endl;count--;}//new 局部重载void *operator new(size_t size){cout << "局部new call" << endl;void *mem = malloc(size);    //内存分配失败,则返回0if (mem)return malloc(size);elsethrow bad_alloc();     //内存分配失败,抛出异常}//new[] 局部重载void *operator new[](std::size_t size){cout << "局部new[] call" << endl;void *mem = malloc(size);    //内存分配失败,则返回0if (mem)return malloc(size);elsethrow bad_alloc();     //内存分配失败,抛出异常}//delete 局部重载void operator delete(void *ptr){cout << "局部delete call" << endl;//不为空,则调用free释放内存if (ptr){free(ptr);}}//delete[] 局部重载void operator delete[](void *ptr){cout << "局部delete[] call" << endl;//ptr不为空,则调用free释放内存if (ptr){free(ptr);}}};int MyClass::count = 0;int main(){cout << "******new delete 局部重载演示***by David***" << endl;cout << "起始MyClass::count = " << MyClass::count << endl;MyClass *my = new MyClass;delete my;cout << "-----------------" << endl;MyClass my1;cout << "-----------------" << endl;MyClass *mys = new MyClass[5];cout << "MyClass::count = " << MyClass::count << endl;delete[]mys;cout << "MyClass::count = " << MyClass::count << endl;cin.get();return 0;}
运行



2.全局重载

对全局的new和delete重载可以监控所有类型的内存分配。

#include <iostream>#include <string>using namespace std;class MyClass{public:MyClass(){cout << "MyClass()" << endl;}~MyClass(){cout << "~MyClass()" << endl;}void *operator new(std::size_t size){cout << "MyClass::new重载" << endl;void *mem = malloc(size);if (mem)return mem;elsethrow bad_alloc();}void *operator new[](std::size_t size){cout << "MyClass::new[]重载" << endl;void *mem = malloc(size);if (mem)return mem;elsethrow bad_alloc();}void operator delete(void *ptr){cout << "MyClass::delete重载" << endl;if (ptr){free(ptr);}}void operator delete[](void *ptr){cout << "MyClass::delete[]重载" << endl;if (ptr){free(ptr);}}};//全局new重载void *operator new(std::size_t size){cout << "全局new重载" << endl;void *mem = malloc(size);if (mem)return mem;elsethrow bad_alloc();}//全局new[]重载void *operator new[](std::size_t size){cout << "全局new[]重载" << endl;void *mem = malloc(size);if (mem)return mem;elsethrow bad_alloc();}//全局delete重载void operator delete(void *ptr){cout << "全局delete重载" << endl;if (ptr){free(ptr);}}//全局delete[]重载void operator delete[](void *ptr){cout << "全局delete[]重载" << endl;if (ptr){free(ptr);}}int main(){cout << "******全局/局部new和delete都进行重载***by David***" << endl;int *p = new int;delete p;cout << "-------------------" << endl;double *ds = new double[10];delete[]ds;cout << "-------------------" << endl;MyClass *my = new MyClass;delete my;cout << "-------------------" << endl;MyClass *mys = new MyClass[3];delete[]mys;cin.get();return 0;}
运行



如果类型重新定义了new 和 delete,则调用局部的,否则调用全局的。


细节

  • operator new或operator new[]的返回类型必须是void*。
  • operator delete或operator delete[]的返回类型必须是void。
  • 类中重载的new和delete都是隐式static的。若显式声明,也不会出错。
  • size_t就是unsigned int。当编译器调用operator new时,把存储指定类型对象所需的字节数传递给size_t的形参。当调用operator new[]时,就传递数组中所有元素的字节数。


编译器对operator new的扩展,更像如下这般:

void *operator new(std::size_t size){if (size == 0) size = 1;//对于size为0,也要保证返回唯一内存地址void *mem = nullptr;try{if (void *mem = malloc(size)){//调用默认的构造函数对分配的内存进行初始化mem = MyClass::MyClass(mem);}}catch (...){throw;}return mem;}




本专栏目录

  • C++拾遗 目录

所有内容的目录

  • CCPP Blog 目录




1 1
原创粉丝点击