1. 程式人生 > >C++之new 和 delete

C++之new 和 delete

new 和 delete要成對使用,且要採取相同形式

使用new時,會發生2件事,1.記憶體被分配出來;2.針對此記憶體會有一個(更多)建構函式被呼叫;

使用delete,發生2件事,1.針對此記憶體的解構函式被呼叫;2.記憶體被釋放;

舉例:

std::string * stringPtr1 = new std::string;

std::string * stringPtr2 = new std::string[100];

delete stringPtr1;

delete [] stringPtr2;

開發人員為了研究學習他們的軟體使用記憶體的行為特徵,然後修改分配和歸還工作,以求獲得其所建置的系統的最佳效率

定製new和delete:主角是operator new和 operator delete,配角是new-handler

瞭解new-handler的行為:

首先介紹客戶指定的錯誤處理函式的使用方法:呼叫set_new_handler

namespace std{

typedef void (*new_handler) ();------new_handler被定義為函式指標

        new_handler set_new_handler(new_handler p) throw(); 返回值是一個指標,指向set_new_handler 被呼叫前正在執行的那個new-handler函式

}

如何為每一個class 設計專屬的new-handlers?需要為class提供自己的set_new_handler和operator new即可。

舉例:

class Widget{

public:

static std::new_handlerset_new_handler(std::new_handler p) throw();

static void* operator new(std::size_t size) throw(std::bad_alloc);

private:

static std::new_handlercurrentHandler;

}

std::new_handler Widget::currentHandler = 0; //Static 成員必須在class 定義式之外定義,除非他們是const且是整數型。

std::new_handler Widget::set_new_handler(std::new_handler p) throw()//標準的set_new_handler

{

std::new_handler oldHandler = currentHandler;

currentHandler = p;

return oldHandler;

}

class NewHandlerHolder{

public:

explicit NewHandlerHolder(std::new_handler nh) : handler(nh){}//防止隱式轉換

~NewHandlerHolder(){std::set_new_handler(handler);} //恢復new_handler

private:

std::new_handler  handler;

NewHandlerHolder(const NewHandlerHolder&);  //拒絕使用複製和賦值構造

NewHandlerHolder& operator=(const NewHandlerHolder&);

}

void * Widget::operator new(std::size_t size) throw(std::bad_alloc)

{

NewHandlerHolder h(std::set_new_hanlder(currentHandler));//儲存全域性的handler

return ::operator new(size);

}

//採用模板方式建立一個複用的baseclass,採用的方式是CRTP

請記住:

set_new_handler 允許客戶指定一個函式,在記憶體分配無法獲得滿足時被呼叫

Nothrow new是一個頗為侷限的工具,因為它只是用記憶體分配;後繼的建構函式呼叫還是可能丟擲異常

瞭解何時在“全域性性的”或“class 專屬的”基礎上合理體寒預設的new和delete。

1. 為了檢測運用錯誤

2. 為了收集動態分配記憶體之使用統計資訊

3. 為了增加分配和歸還的速度

4.為了降低預設記憶體管理器帶來的空間額外開銷

5.為了彌補預設分配器重的非最佳齊位

6.為了將相關物件成簇集中

7.為了獲得非傳統的行為

舉例:對heap 運用錯誤進行除錯的定製new和delete開發

http://blog.sina.com.cn/s/blog_65e729050100m7uw.html

編寫new和delete時需要固守常規

原則:實現一致性operator new必得返回正確的值;記憶體不足時必得呼叫new-handling 函式;

           必須有對付零記憶體需求的準備;避免不慎掩蓋正常形式的new

舉例:滿足前三條

void* operator new(std::size_t size)

{

using namespace std;

if(0 == size){

size = 1;

}

while(true){

void* p = ::operator new(size);

if(null != p) return p;

new_handler globalHandler = set_new_handler(0);

set_new_handler(globalHandler);

if(globalHandler) (*globalHandler)();

else throw std::bad_alloc();

}

}

如果涉及到派生類繼承要如何處理呢?

calss Base{

public:

static void* operator new(std::size_t size) throw(std::bad_alloc);

static void  operator delete(void* rawMemory,std::size_t size) throw();

};

void* Base :: operator new(std::size_t size) throw(std::bad_alloc)

{

if(size != sizeof(base))

return ::operator new(size);

}

void Base::operator delete(void* rawMemory,std::size_t size) throw()

{

if(rawMemory == 0)return ;

if(size != sizeof(Base)){

::operator delete(rawMemory);

return ;

//歸還所指的記憶體

return ;

}

//placement new 和placement delete

placement new的定義如下:

void * operator new(std::size_t, void* pMemory) throw();

步驟一:Widget* pw = new Widget;共有兩個函式被呼叫,1是分配內訓的operator new;一個是Widget的預設建構函式

步驟二:

class Widget{

public;

static void* operator new(std::size_t size,std::ostream& logStream)throw (std::bad_alloc);

static void operator  delete(void* pMemory,sdd::size_t size)throw();

}

如果記憶體分配成功,但是在建構函式中失敗的話,執行期系統會做記憶體的處理,它會找尋域operator new

類似的operator delete,否則就會找不到對應的釋放參數 而導致記憶體洩露。

不要掩蓋正常的operator, 一定要成對出現。

相關推薦

C++new delete

new 和 delete要成對使用,且要採取相同形式。 使用new時,會發生2件事,1.記憶體被分配出來;2.針對此記憶體會有一個(更多)建構函式被呼叫; 使用delete,發生2件事,1.針對此記憶體的解構函式被呼叫;2.記憶體被釋放; 舉例: std::string

C++基礎 newdelete

style 析構函數 對比 pan delete 基本數據類型 交叉 del 報錯 1.new delete 的使用 (1)基本數據類型 int *p = new int(10); delete p; int *p = (int *)malloc(sizeof(int))

C++中newdelete之後發生了什麼

眾所周知,如果我們使用new向系統申請了記憶體,我們應該使用指標指向這一塊記憶體,俾能我們使用結束後,通過delete該指標釋放此記憶體資源。 如果理解只達到這種程度,在記憶體管理稍微複雜一點時便一定會束手無策。總有一些事情比其他事情更基本一點,現在我來談談當我們new和delete之後

C++中newdelete的用法

new和delete運算子用於動態分配和撤銷記憶體的運算子 new用法:           1.     開闢單變數地址空間  

C++newdelete 與malloc、free

在C/C++程式設計中經常會申請記憶體,而對記憶體的申請釋放操作有兩套方法: new、delete 與malloc、free。 1. 區別 (1). new、delete是c++中的操作符,malloc、free是C中的一個函式,它們都可用於申請動態記憶體和釋放記憶體。 (2)

C++中newdelete的背後

NewTest!wmain: 00aa1020 56              push    esi 00aa1021 6a04            push    4  00aa1023 e8b4030000      call    NewTest!operator new (00aa13d

C++重寫newdelete,比想像中困難

  關於C++記憶體管理這話題,永遠都不過時。在我剛出道的時候,就已經在考慮怎麼檢測記憶體洩漏(https://www.cnblogs.com/coding-my-life/p/3985164.html)。想用一份簡單的程式碼,並且不太影響執行效率去實現記憶體洩漏檢測,是不太現實的。當時覺得重寫new和del

c++中newdelete的區別

new 和delete 是運算子,而不是函式。 new new 運算子的格式: new 型別[初值]; new int; ///開闢一個存放整數的儲存空間,返回一個指向該儲存空間的地址

C++回顧——newdelete

一、物件的建立 當建立一個C++物件時,會發生兩件事: 1)為物件分配記憶體; 2)呼叫建構函式來初始化那個記憶體(C++強迫這樣做是因為未初始化的物件是程式出錯的主要原因) C++把建立一個物件所需要的所有動作都結合在一個稱為new的運算子裡(分配記憶

c++的newdelete的方法使用以及不用new定義變數

new和delete運算子用於動態分配和撤銷記憶體的運算子 new用法:           1.     開闢單變數地址空間                1)new int;  //開闢一個存放陣列的儲存空間,返回一個指向該儲存空間的地址.int *a = ne

C++:NewDelete的用法

//C++裡 陣列new 和delete問題 //對於陣列new的不同方式 和不同的釋放方法 //---------------------------------------------

C++ 類(newdelete運算子)

文章概述 new和delete運算子 new和delete運算子 a. new/delete 是C++的運算子;類似於malloc/free,程式執行(動態)得開闢記憶體空間(堆); b. new 可以為內建型別的變數開闢空間,陣列變數,類的物件

C++中newdelete

New運算子 1、new表示式: 當我們使用一條new表示式時: string *sp=newstring(“a value”); string *arr=newstring[10]; 實際上執行了三步操作。第一步,new表示式呼叫一個名為operatornew(或者ope

C++分析NewDelete----C語言MallocFree

C++中為什麼不用Malloc和Free,而用New和Delete?   <1> 如圖: 類的物件在堆上分配的時候用malloc和free: 我們觀察發現雖然在堆上申請空間了,但並沒有呼叫

c++中newdelete的預設賦值測試

  為了測試c++中對new操作符的運算規則是否呼叫預設物件的建構函式進行初始化,故寫出如下的測試demo: #include <iostream> using namespace std;

2.16 C++類與newdelete操作符

運行 out 可能 clas cout std 存儲 分配 程序 參考: http://www.weixueyuan.net/view/6347.html 總結:    當我們需要為類對象動態分配存儲空間時,我們應該使用C++語言提供的new與new[]操作符,而不要使用C

c++中的newdelete

程序設計 wan https 解決 運算符 AI 指向 log cnblogs 對於計算機程序設計而言,變量和對象在內存中的分配都是編譯器在編譯程序時安排好的,這帶來了極大的不便,如數組必須大開小用,指針必須指向一個已經存在的變量或對象。對於不能確定需要占用多少內存的情況,

effective c++ 條款16:成對使用newdelete時要采用相同形式

最好 class 你在 pan TE fec IV line PE 記住: 如果你在new表達式中使用[ ],必須在相應的delete表達式中也是用[ ]。如果你在new時不使用[ ],一定不要在delete時使用[ ]。 string* stringPtr1 = n

effective c++條款16:成對使用newdelete時要採取相同形式

下面的程式碼會產生什麼樣的後果? #include <iostream> using namespace std; int main(void) { std::string *StringArray = new std::string[30]; delete StringAr

effective C++筆記--定製newdelete(二)

文章目錄 編寫new和delete時需固守常規 寫了placement new也要寫 placement delete 編寫new和delete時需固守常規 . 在編寫自己的operator new和operator delete時,需要