#new与delete回顾
new:先分配memory内存,在调用ctor构造函数。
#转换方式
- Complex类
class Complex{ public: Complex(int _m_real,int _m_imag): m_real(_m_real),m_imag(_m_imag){ } private: double m_real; double m_real; };
- 创建类对象
Complex* pc=new Complex(1,2);
- 编译器转换
void* mem=operator new(sizeof(Complex)); pc=static_cast<Complex*>(mem); pc->Complex::Complex(1,2);
- 图模型
delete:先调用dtor,在释放memory
- 调用析构函数
delete pc;
- 编译器转换为
Complex::~Complex(pc); operator delete(pc);
- 图模型
- #补充:表达式行为不可改变,即不能重载也即 new 所分解出1,2,3 delete 所分解出1,2的事实不可改变。但是分解后的函数可以重载。
- #补充:析构函数并不释放内存,释放内存为独立操作。
#重载(全局)::operator new new[] 或者 重载::operator delete delete[]
- 全局函数
void* myAlloc(size_t size){ return malloc(size); } void myFree(void* ptr){ return free(ptr); }
- 上述四个函数重载实例
inline void* operator new(size_t size){ cout << "global new() " <<endl; return myAlloc(size); } inline void* operator new[](size_t size){ cout << "global new[]() " <<endl; return myAlloc(size); } inline void operator delete(void* ptr){ cout << "global delete() " <<endl; myFree(ptr); } inline void operator delete[](void* ptr){ cout << "global delete[]() " <<endl; myFree(ptr); }
- #补充:new需要一个参数,开辟内存空间的大小。delete需要传递指向需要销毁内存的指针,以便销毁内存。
#重载member operator new/delete
- #提示:对类中的成员做重载。
- Foo类
class Foo{ public: void* operator new(size_t); void operator delete(void*,size_t); };
- 构造函数与析构函数调用
Foo* p = new Foo; delete p;
- 编译器转换方式
try{ void* mem = operator new(sizeof(Foo)); p = static_cast<Foo*>(mem); p->Foo::Foo(); }
p->~Foo(); operator delete(p);
- 图模型
#重载member operator new[]/delete[]
#需要注意new与delete的语法规则,与重载函数的语法规则。同时注意内部函数写法。
- Foo类
class Foo{ public: void* operator new[](size_t); void operator delete[](void*,size_t); };
- 构造函数析构函数调用
Foo* p = new Foo[N]; delete[] p;
- 编译器转换方式
try{ void* mem = operator new(sizeof(Foo)*n+4); p->Foo::Foo(); } p->~Foo(); operator delete(p);
- 图模型
#示例程序
- Foo类
class Foo{ public: int _id; long _data; string _str; public: Foo():_id(0){ cout << "default ctor.this= " << this <<endl; } Foo(int i):_id(i){ cout << "ctor.this=" << this << "id=" <<_id <<endl; } ~Foo(){ cout << "dtor.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); cout<<"new"<<endl; return p; } void Foo::operator delete(void* pdead,size_t size){ cout << "delete" <<endl; free(pdead); } void* Foo::operator new[](size_t size){ Foo* p = (Foo*)malloc(size); cout << "new[]" <<endl; return p; } void Foo::operator delete[](void* pdead,size_t size){ cout << "delete[]" <<endl; free(pdead); }
- 调用构造函数与析构函数
int main(){ Foo* pf = new Foo; delete pf; Foo* pf1 = ::new Foo; ::delete pf1; return 0; }
#补充:强制全局new与delete可用::new ::new[] ::delete ::delete[]。同样若没有全局函数大可不必这样写,其直接调用全局函数。
#内存结构探索
- 代码示例

#include <iostream> #include <string> using namespace std; class Foo{ public: int _id; long _data; string _str; public: Foo():_id(0){ cout << "ctor.this = " << this<<endl; } ~Foo(){ cout << "dtor.this = " << this<<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); cout <<"Foo::operator new() "<<"size ="<<size<<endl; return p; } void Foo::operator delete(void* pdead,size_t size){ cout << "Foo::operator delete() "<<"size ="<<size<<endl; free(pdead); } void* Foo::operator new[](size_t size){ Foo* p = (Foo*)malloc(size); cout << "Foo::operator new[] "<<"size ="<<size<<endl; return p; } void Foo::operator delete[](void* pdead,size_t size){ cout << "Foo::operator delete[] "<<"size ="<<size<<endl; free(pdead); } int main(){ Foo* pf = new Foo; delete pf; Foo* pf1 = new Foo[5]; delete[] pf1; // Foo* pf1 = ::new Foo; // ::delete pf1; return 0; }
- 运行结果
#补充说明
由运行结果可以分析得出,构造函数的内存分配由上至下,析构函数的内存释放由下至上。并且,对于对象数组其内存会多分配8个字节,用来存放对象数组相关信息。
#重载new() delete()
class member operator new() 可以重载出多个版本,但是其必须符合重载要求每个声明都要有独特的参数列,其中第一个参数必须是size_t,其余参数以new所指定的placement arguments为初值。出现new()小括号内的记为placement arguments。
- 示例
Foo* pf = new(300,'c')Foo;
同时可以重载class member operator delete()但是并非必须。重载的delete被调用时当且仅当new所调用的ctor构造函数抛出异常exception。之所以被这样调用,主要是用来归还未能完全创建成功的对象object所占用的memory。
- 测试实例

#include <iostream> using namespace std; class Foo{ public: Foo(){ cout<<"Foo::Foo()"<<endl; } Foo(int){ cout<<"Foo::Foo(int)"<<endl; } //operator new() 重载 void* operator new(size_t size){ return malloc(size); } //标准库提供placement new() 的重载 void* operator new(size_t size,void* start){ return start; } //新的placement new void* operator new(size_t size,long extra){ return malloc(size+extra); } //新的placement new void* operator new(size_t size,long extra,char init) { return malloc(size+extra); } //故意写错 // void* operator new(long extra,char init){ // return malloc(extra); // } //一般operator delete()的重载 void operator delete(void*,size_t){ cout<<"operator delete(void*,size_t"<<endl; } //对应2 void operator delete(void*,void*){ cout<<"operator delete(void*,void*)"<<endl; } //对应3 void operator delete(void*,long){ cout << "operator delete(void*,long)"<<endl; } //对应4 void operator delete(void*,long,char){ cout<<"opertor delete(void*,long,char)"<<endl; } }; int main(){ Foo start; Foo* p1 = new Foo; Foo* p2 = new(&start)Foo; Foo* p3 = new(100)Foo; Foo* p4 = new(100,'a')Foo; Foo* p5 = new(100)Foo(1); Foo* p6 = new(100,'a')Foo(1); Foo* p7 = new(&start)Foo(1); Foo* p8 = new Foo(1); return 0; }
#补充:测试代码写错部分在dev C++ 中无法编译通过。侯捷老师在不同版本编译器中,编译通过后可运行跳转到自定义delete中,而另一款编译器编译通过后,并没有跳转自定义delete。
另外即使不写出一一对应的delete也不会有任何报错,编译器编译通过会报warning,显示出自动放弃检查警告。
#Basic_String
- basic_string 使用new(extra)扩充申请量

class basic_string{ private: void release() { if(--ref==0){ delete this; } } inline static void* operator new(size_t,size_t); inline static void operator delete(void*); inline static Rep* create(size_t); }; basic_string<charT,traits,Allocator>::Rep:: create(size_t extra){ extra = frob_size(extra+1); Rep* p = new(extra)Rep; return p; } template<class charT,class traits,class Allocator> inline void* basic_string<charT,traits,Allocator>::Rep:: operator new(size_t,size_t extra){ return Allocator::allocate(s+extra*sizeof(charT)); }
#补充说明:此为侯捷老师添加标准库代码的例子,例子并不完整,摘抄其中一部分代码,new 调用时经过成员函数create的调用得到调用。