感謝原文作者,為我揭開C++又一個盲點。
原文位址:http://blog.csdn.net/bichenggui/article/details/4823978
關于c++ new操作符的重載
你知道c++ 的new操作符和operator new的差別麼?也許你還會問,他們有差別嗎?
當你寫下面這樣的代碼時,
string *pa = new string("memory managerment");
你使用的是new操作符,這個操作符和sizeof一樣,是c++語言級别支援的。你不能改變它的語義,它做的事情總是不變的:配置設定足夠的記憶體以容納對象,然後調用構造函數初始化上一步所配置設定的記憶體。New操作符總是做這兩件事情,你不能改變它的行為。
你所能改變的隻是第一步的行為,如何為對象配置設定RAW記憶體。operatornew函數用來為對象配置設定原始記憶體。New操作符的第一步調用的就是operator new。你可以重載這個函數。它的原型如下:
Void* operator new(size_t size);
函數的傳回值是void*, 因為這個函數傳回的是指針。這個指針指向原生的,為初始化的記憶體。其語義就像malloc。實際上它内部調用的就是malloc。參數size指定待配置設定的記憶體大小。你可以在重載的時候加上額外的參數,但是第一個參數類型必須是size_t.
絕大多數情況下,你不需要調用operator new,萬一你需要調用它,調用的格式是這樣的:
Void* rawmemory = operator new(sizeof(string));
函數operator new将傳回一個指針,指向一塊足夠容納一個string對象的記憶體。
就像malloc一樣,operator new的唯一的職責就是配置設定記憶體,它對構造函數一無所知。把operator new傳回的未初始化的指針構造成一個對象是new操作符的工作。當你的編譯器遇到以下的代碼時:
它生成的僞代碼類以如下:
Void* memory = operator new(sizeof(string));
call string::string("memory managerment") onmemory;
string* Pa = static_cast<string*>(memory);
第二布包含了構造函數的調用。這是你的編譯器調用的。那麼你不緊會問,程式員可以手動調用構造函數嗎?答案是否定的。但是編譯器同時給你提供了另外一個折中,是你可以達到這個目的。
需要說明的是,在一個已存在的對象上調用構造函數是沒有任何意義的。因為構造函數用來初始化對象。但是有時候有一些記憶體已經被配置設定但是尚未初始化,你需要在這些記憶體中構造一個對象。你可以使用operator new函數的一個特殊版本。一個術語叫 placement new的函數來做這件事情。
回到前面那個字元串的例子,我們可以這樣使用placement new:
String* pa = new (memory) string("memorymanagerment");
以上兩句就相當于new 操作符所做的事情了。
這就是operator new和placement new的全部秘密。一般的來說,你不需要重載和顯式調用這兩個函數。