重载::operator new,::operator new[],::operator delete,::operator delete[](加了::表示全局的)
小心,这些影响非常广,因为重载的是全局的
void* myAlloc(size_t size)
{ return malloc(size); }
void myFree(void* ptr)
{ return free(ptr); }
这些函数是给编译器调用的
它们不可以被声明于一个namespace内
//重载operator new
inline void* operator new(size_t size)
{ cout << "global new() \n"; return myAlloc( size ); }
//重载operator new[]
inline void* operator new[](size_t size)
{ cout << "global new[]() \n"; return myAlloc( size ); }
//重载operator delete
inline void operator delete(void* ptr)
{ cout << "global delete() \n"; myFree( ptr ); }
//重载operator delete[]
inline void operator delete[](void* ptr)
{ cout << "global delete[]() \n"; myFree( ptr ); }
重载member operator new/delete
对class内的成员operator new/delete进行重载
class Foo {
public:
void* operator new(size_t);//size_t为对象的大小
void operator delete(void*,size_t);//size_t可有可无
...
};
应用
创建指针p并使用后,将其删除,以释放内存
Foo* p = new Foo;
...
delete p;
分解上述应用,进行分析:
创建指针p
Foo* p = new Foo;
分解为三步:
try {
void* mem = operator new(sizeof(Foo));
p = static_cast<Foo*>(mem);
p->Foo::Foo();
}
删除指针p,以释放内存
delete p;
分解为两步:
p -> ~Foo();
operator delete(p);
重载member operator new[] / delete[]
对class内的成员operator new[] / delete[]进行重载
[ ]表示数组
class Foo {
public:
void* operator new[] (size_t);//size_t为数组大小
void operator delete[] (void*,size_t);//size_t可有可无
...
};
应用
创建指针p并使用后,将其删除,以释放内存
Foo* p = new Foo[N];
...
delete [ ] p;
分解上述应用,进行分析:
创建指针p
Foo* p = new Foo[N];
分解为三步:
try {
void* mem = operator new(sizeof(Foo)*N + 4 );//对象大小×数组大小N
p = static_cast<Foo*>(mem);
p->Foo::Foo(); //N次
}
删除指针p,以释放内存
delete [ ] p;
分解为两步:
p -> ~Foo(); // N次
operator delete(p);
示例
设计者设计class Foo
如果使用者这样写
Foo* pf = new Foo;
delete pf;
调用的是以下两个函数
void* Foo::operator new(size_t size){
Foo* p = (Foo*)malloc(size);
cout << ...
return p;
}
void Foo::operator delete(void* pdead, size_t size){
cout << ...
free(pdead);
}
如果使用者这么写:
Foo* pf = ::new Foo;
::delete pf;
就是调用的以下两个函数:
若无member就调用global(::表示全局的)
void* ::operator new(size_t);
void ::operator delete(void*);
static void* operator new(size_t size);
static void* operator new[](size_t size);
static void operator delete(void* pdead, size_t size);
static void operator delete[](void* pdead,size_t size);
上述四个函数的部分内容示范
void* Foo::operator new(size_t size){
Foo* p = (Foo*)malloc(size);
cout << ...
return p;
}
void* Foo::operator new[](size_t size){
Foo* p = (Foo*)malloc(size);
cout << ...
return p;
}
void Foo::operator delete(void* pdead, size_t size){
cout << ...
free(pdead);
}
void Foo::operator delete[](void* pdead,size_t size){
cout << ...
free(pdead);
}
Foo without virtual dtor
cout << "sizeof(Foo)=" << sizeof(Foo);
Foo* p = new Foo(7);
delete p;
Foo* pArray = new Foo[5];
delete[] pArray;
class Foo中元素大小sizeof=12
(int _id是4 byte,long_data是4 byte,string _str中string其实是一个指针占4 byte)
Foo* pArray = new Foo[5];
一个sizeof=12这里有5个,所以size=60,但这里size=64
4表示下面有4个元素,5*12+4=64
- 构造(construct)时从上往下调用构造函数,this指针随着从上往下
- 析构(destruct)时从下往上调用析构函数,this指针随着从下往上
执行构造时调用5次构造
Foo* pArray = new Foo[5];
执行析构时调用5次析构
最后用delete[ ]释放内存
delete[ ] pArray;
Foo with virtual dtor
只要类中有虚函数,它的对象就会多一个指针
cout << "sizeof(Foo)=" << sizeof(Foo);
Foo* p = new Foo(7);//new一个单一对象
delete p;
Foo* pArray = new Foo[5];
delete[] pArray;
只要类中有虚函数,它的对象就会多一个指针
class Foo中元素大小sizeof=12,加一个指针4 byte,12+4=16
(int _id是4 byte,long_data是4 byte,string _str中string其实是一个指针占4 byte)
Foo* pArray = new Foo[5];
一个sizeof=16这里有5个Foo,所以size=80,但这里size=84
4表示下面有4个元素,5*16+4=84
- 构造(construct)时从上往下调用构造函数,this指针随着从上往下
- 析构(destruct)时从下往上调用析构函数,this指针随着从下往上
执行构造时调用5次构造
Foo* pArray = new Foo[5];
执行析构时调用5次析构
最后用delete[ ]释放内存
delete[ ] pArray;