1.在之前的笔记中已经提到,new在编译器下会分成三个动作,当有重载就会跑到重载之中。
先看一个代码:
void* myAlloc(size_t size)
{
renturn malloc(size);
}
void myFree(void* ptr)
{
return free(ptr);
}
再看一个重载:
inline
void* operator new(size_t size)
{
return myAlloc(size);
}
inline
void* operator new[](size_t size)
{
return myAlloc(size);
}
inline
void operator delete(void* ptr)
{
myFree(ptr);
}
inline
void operator delete[](void* ptr)
{
myFree(ptr);
}
这里要注意一个影响,现在我们是在重载一个全局的东西。
2.当然我们还能重载member中的new与delete。
class Foo
{
public:
void* operator new[](size_t);
void operator delete[](void* ptr);
...
};
应用:
Foo* p = new Foo[N];
delete[] p;
这里讨论new[]与delete[]
当Foo* p = new Foo[N];
会调用Foo::Foo() N次。
3.看看具体的示例:
class Foo
{
public:
int _id;
long _data;
string _str;
public:
Foo():_id(0) {cout<<"default ctor.this="<<this<<"id="<<_id<<endl;}
Foo(int i):_id(i) {cout<<"ctor.this="<<this<<"id="<<_id<<endl;}
~Foo() {cout<<"ctor.this="<<this<<"id="<<_id<<endl;}
static void* operator new(size_t size);
static void operator delete(void* pdead,size_t size);
static void* operator new[](size_t size);
static void operator delete[](void* pdead,size_t size);
};
void* Foo::operator new(size_t size)
{
Foo* p = (Foo*)malloc(size);
return p;
}
void Foo::operator delete(void* pdead,size_t size)
{
free(pdead);
}
void* Foo::operator new[](size_t size)
{
Foo* p = (Foo*)malloc(size);
return p;
}
void Foo::operator delete[](void* pdead,size_t size)
{
free(pdead);
}
假设使用:
Foo* pf = new Foo;
delete pf;
//如果使用者想要绕过这些重载
Foo* pf = ::new Foo;
::delete pf;
//这样就会调用全局的:
void* ::operator new(size_t);
void ::operator delete(void*);
可以看到一个Foo占有12字节。
单纯从代码很难看出端倪,我们去编译器中具体运行一下试试:
#include "stdafx.h"
#include "Foo.h"
int main()
{
Foo *pa = new Foo();
cout << endl;
delete pa;
cout << endl;
cout << endl;
Foo *pb = new Foo[5];
cout << endl;
delete[] pb;
return 0;
}
结果图:
这里就能很清楚的看清楚new delete 与new[] delete[] 的区别。
4.具体讨论一下关于sizeof的关系。
分两种情况:
(1)Foo without virtual
Foo *pa = new Foo();
Foo *pb = new Foo[5];
我们直到在Foo中有三个数据,一共是12个字节,那么第一行代码的pa必然是12字节,
但是,pb理论上应该是60字节,但是却占有64个字节,为什么?因为还有一个4字节的内存上显示5,代表有五个。
(2)Foo with virtual
如同上一个那样运行,我们会发现,pa是占有16字节内存,为什么?如同之前关于虚机制的vptr vtbl的笔记中有说,虚函数的类中肯定会有一根vptr。
pb中占有84字节!!!!
5.再来验证一下关于绕过自己重载的new与delete
我们先在重载的new delete中都加上:cout<<"1"<<endl;
运行之前的调用:
运行绕过的代码:
// 关于重载new与delete.cpp: 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "Foo.h"
int main()
{
Foo *pa = ::new Foo();
cout << endl;
::delete pa;
cout << endl;
cout << endl;
Foo *pb = ::new Foo[5];
cout << endl;
::delete[] pb;
return 0;
}
运行结果: