我們又瞭解new多少呢?
關於new操作符,我們在對空間的請求(對於類來說)上一共進行兩步:
對於new:先進行空間分配,再進行調用構造函數。
在new與delete中的第二步,實際上都是調用一個全局函數operator new/delete對空間進行分配/回收。
在這個全局構造函數中::operator new 有6個重載,其中有三個是關於數組空間的分配。
如下:
void *operator new(std::size_t count) throw(std::bad_alloc); // 一般的版本
void *operator new(std::size_t count,new const std::nothrow_t&) throw(); // 內存分配失敗不會拋出異常
void *operator new(std::size_t count, void *ptr) throw(); <span style="white-space:pre"> </span> //placement 版本 <span style="font-family: Arial, Helvetica, sans-serif;"> </span>
void *operator new[](std::size_t count) throw(std::bad_alloc);
void *operator new[](std::size_t count, const std::nothrow_t&) throw();
void *operator new[](std::size_t count, void *ptr) throw();
對於一般版本,爲了兼容早期new而不拋出異常的版本 ,我們已經用的很熟練了,我們只談一談placment new 版本。
區分new 操作符與operator new 函數是十分重要的,對於new操作符,我們不可以重載所以new操作符的行爲是確定的,而operator new是可以進行重載的,對其進行替換的 。但對於placement new 版本,在c++標準中已經明令禁止我們去重載這個版本,對於其它版本我們可以任意的去替換掉(說是這麼說但實際上並不贊同這樣做)。
爲什麼c++嚴禁我們去重載這個placement new 這個函數呢,palcement new 與其它重載版本不同它實際上並不會分配任何空間,僅僅返回一個可能指向空間的指針。
因此我們不能對placemen newt進行delete操作。
可能有人會問對於placement new有什麼作用?
我們在創建一個對象的時候,我們可能不想給它初始化,我們希望遲一點初始化,這時候,而我們提前對它的初始化就是十分浪費效率的。
我們就可以這樣做
A *number0 = static_cast<A*>(::operator new(sizeof(A)));
new(number0)A();
對於operator new(size_t);實際上與memory.h頭文件中的malloch函數效果是一樣的的。
通常對placement new也搭配一些其它操作,一般來說這個是必要的,我們必須對一個類對象進行析構,不過直接對一個對象進行析構十分不妥的,我們需要對這個析構進行一下封裝。
實際上,對於一個類而不是語言內嵌類型,對於一個new與delete的操作實際上是分成三步的,多了一步,我們在進行operator new 調用之前會先查找class內是否有這個operator new 的重載,如果有我們會調用class中的重載版本,有一點就算我們把operator new 聲明爲私有類成員,編譯器也只會提示一個類成員不可調用,也不會調用全局的operator new。
我們在開始說placement new 重載是明令禁止的,但這個要求僅限於全局,我們在類中仍可以定義一個“placement new”。
還有一點,對於類內重載的operator new/delete是靜態成員函數, 因爲他用不到this指針。所以operator new/delete是可以被繼承的,
關於數組的說明:
!只有一點
我們對於數組的分配方法
A *number1 = static_cast<A*>(::operator new[](sizeof(A)*2));
A *number2 = new A[2];
第二種相對於第一種可能會略微增加內存。關於operator new我們可能面臨這樣一個錯誤,當我們無法知道一個類是否已經重載operaotr的時候,我們就面臨着一個很危險的行爲,我們無法準確的對這個類進行異常的判斷此時我們必須將所有的operator new都使用全局版本。
一般的來說我們在重載operator new 的時候一般也會重載operator delete 如果一個類的operator new 分配失敗則,這個類將調用operator delete 進行回收。