進一步瞭解new操作符

我們又瞭解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 進行回收。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章