new和delete續

一、單參數的重載

在上次new和delete的講解中已經說明了new和delete運作的過程和內存中其運行過程,這裏補充的是重載::operator new,::operator delete以及[]的形式

不過一旦重載了這2個操作符,影響是無窮無盡的,謹慎。

void* myAlloc(size_t size)
{ return malloc(size);}
void myfree(void* ptr)
{ return free(ptr);}

//它們不可以被聲明在一個namespace裏面
inline void* operator new(size_t size)
{
	cout << "global new()" << endl;
	return myAlloc(size);
}
inline void* operator new[](size_t size)
{
	cout << "global new[]()" << endl;
	return myAlloc(size);
}
inline void operator delete(void* ptr)
{
	cout << "global delete()" << endl;
	myfree(ptr);
}
inline void operator delete[](void* ptr)
{
	cout << "global delete[]()" << endl;
	return myfree(ptr);
}
接下來看一下成員函數的new和delete重載
在成員函數裏,寫法和原來全局的基本類似,在創建Foo指針p的時候,先創建一個臨時指針並且開闢一塊空間給它,再將整個臨時指針強制轉換爲p的類型,同時賦值給p,再進行p的對象的構造。

如果是delete的話,這時候先對整個對象進行析構,再釋放這塊內存。

如果是new[]和delete[]的話,傳入的大小需要改變爲sizeof(foo)*n,當然在這塊內存裏面,我們需要進行n個對象的構造。進行析構的時候也是一樣,析構n個,然後釋放總的內存

下面是一個具體的例子,同樣的是創建一個p指向new的Foo對象,如果沒有member operator new和delete就使用全局的

如果想直接採用全局的new就需要使用下面的寫法

Foo* pf = ::new Foo;
::delete pf;

在上面對於成員操作符new和delete進行重載的時候,爲了防止出錯,首先先分配了內存,保證最基本的實現。

如果對於一個對象new分配的大小那麼是多少呢,如果是new就是簡單的創建一個大小,如果有虛函數,會加上一個虛指針的大小。

如果對於new[]分配的時候,會多出一塊小內存(4個字節),來表示到底new了多少個對象大小的內存。


二、多參數的重載

使用如下

Foo* pf = new(300,'c') Foo;
傳入了三個參數,第一個是size_t,第二個是300,第三個是'c'。

稱爲placement new.

但是這時候delete也可以重載,也可以重載class member operator delete(),寫出多個版本。但是它們絕對不會被delete調用,只有當new所調用的構造函數拋出異常的時候,纔會調用這些重載的operator delete().它只可能這樣被調用,主要爲了歸還未能完全創建成功的object所佔用的memory.

例子
測試所有的new,在foo(1)的時候拋出異常了,應該調用對應的delete。

三、標準庫裏string類使用placement new實現reference counting


當調用rep的creat函數的時候,會傳入一個大小,這個大小是string存放內容的大小,rep表示的是類,裏面會含有count。

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