关于new operator, operator new, placement new

来源:互联网 发布:随身带着淘宝到异界 编辑:程序博客网 时间:2024/05/19 02:30

       很久前就知道有这三个东西,除了第一个经常用,其他两个仅仅是知道有这个概念。

       前几天在写一个内存池的例子,需要用到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++》

原创粉丝点击