时间:2014.03.12
地点:基地
------------------------------------------------------------------------------
一、简述
先看这样的代码:
string* ps=new string("HuNanUniversity");这是new operator的用法,它的包含两个动作,一是分配足够的内存,用来放置类型对象。比如上述它会分配一个足够放置string对象的内存块出来;二是调用构造函数,为刚刚分配的内存中的对象设定初值。人们常说的new一个东西出来,即总是做这两件事。但可以改变内存的分配行为,只要重载操作符new就OK。
------------------------------------------------------------------------------
二、new对象时的实质
函数operator new通常这样声明:
void* operator new(size_t size);返回值类型是void* ,是一个指针,指向一块最原始的、未初始化的内存。size表示需要分配多少内存。我们甚至可以像其他函数一样调用它,比如:
void* rawMemory=operator new(sizeof(string));这里operator new会返回一个指针,指向一块足够容纳一个string对象的内存。和malloc一样,operator new的唯一任务就是分配内存,而将内存转换为一个存有内容的对象是new operator的责任。比如上述第一个段代码,表面上我们只new了对象,未涉及内存分配,但这样一个语句会产生如下代码:
void* memory=operator new(sizeof(string));//取得原始内存,用来放置一个string对象 call string::string("HuNanUniversity") on *memory; //将内存中的对象初始化 string *ps=static_cast<string*)(memory); //将指针类型做转换,让ps指向新完成的对象
------------------------------------------------------------------------------
三、placement new
有时当你得到一块原始内存,你想在上面构建对象时需要用到placement new,程序员直接调用构造函数是不被许可的。比如:
class Widget{ public: Widget(int widgetSize); ... }; Widget* constructWidgetInBuffer(void* buffer,int widgetSize){ return new (buffer) Widget(widgetSize); }上面的constructWidgetInBuffer函数返回一个指针,指向Widget object,它被构造于传递给函数的一块内存缓冲区上,即buffer指向的原始内存块上。有些应用对象必须置于特定的地址,那么现在placement new就有用了。
一下解释 new(buffer) Widget(widgetSize)
这是new operator的用法之一,额外的变量buffer将作为new operator隐式调用operator new所用。此时operator new除了接受 size-t自变量之外还接受一个void*参数,指向一块内存,准备用来接受在这之上构建的对象,即这里的buffer。看起来就是这样;
void* operator new(size_t,void* location){ return location; }operator new的目的就是要为对象找到一块内存,然后返回一个指针指向该内存。在placement new场景下,因为已经知道目的内存了,不需要再去寻找了,如此简单返回这块内存即可,placement new要做的就是将他自己获得的指针再次返回。
------------------------------------------------------------------------------
四、总结
如果你希望将对象产生于堆上,使用new operator,比如:new int(20); new string("ChangSha");它实际上是执行分配内存和自动调用构造函数在内存上构建对象。如果只打算分配内存,调用operator new即可获得原始内存分配,还可以写自己的operator new决定内存分配方式,这时使用new operator时会自动调用你写得operator new分配内存。要是打算在你已分配的内存中构建对象,使用placement new即可。