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) //内存分配失败,则返回0
return mem; //return malloc(size);
else
throw 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); //内存分配失败,则返回0
if (mem)
return malloc(size);
else
throw bad_alloc(); //内存分配失败,抛出异常
}
//new[] 局部重载
void *operator new[](std::size_t size)
{
cout << "局部new[] call" << endl;
void *mem = malloc(size); //内存分配失败,则返回0
if (mem)
return malloc(size);
else
throw 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;
else
throw bad_alloc();
}
void *operator new[](std::size_t size)
{
cout << "MyClass::new[]重载" << endl;
void *mem = malloc(size);
if (mem)
return mem;
else
throw 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;
else
throw bad_alloc();
}
//全局new[]重载
void *operator new[](std::size_t size)
{
cout << "全局new[]重载" << endl;
void *mem = malloc(size);
if (mem)
return mem;
else
throw 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;
}
本专栏目录
所有内容的目录