很久前就知道有这三个东西,除了第一个经常用,其他两个仅仅是知道有这个概念。
前几天在写一个内存池的例子,需要用到operator new 和 placement new,这才想着去翻书弄明白这两个概念。
new operator 就是我们平时的 new 一个对象。而这个new operator 包含两个操作:1.申请内存。2.在这个内存上调用构造函数,构造一个对象。默认情况下,是向操作系统申请内存。如果需要频繁地new一个对象,并析构对象。这将使得程序性能下降。所以人们就想出了内存池,先向操作系统申请比较多的内存。之后,要构造一个对象时,就在这些已经申请的内存上构建。
这时得改变一下 new operator的行为了。因为它默认是向操作系统申请内存。现在得改成向我们的内存池申请内存。这就需要为这个类定义一个operator new 函数。一般的定义如下:
void* operator new (size_t size);
这个函数可以有多个参数,但第一个参数必须是size_t, 他用来指定要申请的内存的大小。只要一个类定义了这个函数,当为这个类new 一个对象时,new operator就会自动调用这个函数获取内存,然后再在这个内存上调用构造函数。
一般来说,定义了operator new 就要定义operator delete。定义如下:
void operator delete(void* p);
因为,当你要销毁一个对象时,使用delete operator。这个delete operator 和 new operator 相对应:先显示地调用这个对象的析构( p->~XXX() )函数,然后再去释放该对象所占的内存。同样,默认情况下是向操作系统归还内存。如果我们定义了operator new,是向内存池申请的内存,那么就要通过调用一个operator delete,在这个函数里面向内存池归还内存。当定义了这个函数。我们写delete p这个的语句时,编译器先显示地调用析构函数p->~XXX()。然后调用operator delete函数。
当你真正去实现一个内存池和这样的一个对象时,你就猛然会发现:很难为每一个使用了内存池的类 编写operator new 和operator delete函数。一来麻烦,二来之前写的类不太可能重新修改。 这就轮到placement new出场了。
我们可以直接向内存池申请内存。假如有一个类A,并且有一个以int为参数的构造函数。我们可以这样写:
void* p = MemoryPool::alloc(sizeof(A)); //获取内存
A* pa = new (p) A(23);
意思就是,在内存p上调用构造函数A(23)。
当我们要销毁这个对象时,这样写:
pa->~A(); //显示地调用析构函数
MemoryPool::free(p);
当你定义了operator new函数,以后你new一个对象时,将通过你写的operator new函数获取内存。
placement new 则是,你手头上有一块内存,你可以在这块内存上构造一个对象。
参考书籍:《More Effective C++》