程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> new表達式,operator new和placement new介紹

new表達式,operator new和placement new介紹

編輯:C++入門知識

new/delete是c++中動態構造對象的表達式 ,一般情況下的new/delete都是指的new/delete表達式,這是一個操作符,和sizeof一樣,不能改變其意義。

new/delete表達式的聲明如下:

::(optional)  

除了全局作用符::和初始化參數,還有個 placement_params,這是不常見的,要理解這個參數的作用,就要了解operator new和placement new。

眾所周知,new表達式做了兩個工作:1.分配內存;2.在分配的內存上調用構造函數構造對象。比如我們分配一個string對象

string *str = new string(“Kian”);

編譯器首先調用operator new分配一塊內存,類似於malloc,然後在mem上面調用構造函數,

1.void *mem = operator new(sizeof(string));

2. create string at men.

第二步我們是控制不了的,但是operator new卻是可以修改的。

Operator new/delete的聲明如下:

*  *    ( std::size_t count,  std::nothrow_t&  delete  ( *  delete  ( * ptr,  std::nothrow_t& tag);

第二種帶參數tag的聲明稱為nothrow形式,因為現在的operator new如果分配內存失敗的話會拋出bad_alloc異常. 有時候我們不想拋出異常,而是根據返回值判斷內存分配失敗與否,nothrow形式就是這個作用,失敗時不拋出異常,而是返回null指針。

我們可以直接重載operator new, 定制自己的內存分配策略,常見的作用是優化內存使用性能。重載operator new不需要看見聲明就可以直接使用。我們重定義一個簡單的版本:

*    delete( * *i =  ( *str =  std::(

運行結果:

operator new called, size=4

operator delete called

operator new called, size=4

operator new called, size=17

operator delete called

operator delete called

可是有時候我們希望擁有更多的功能,比如記錄內存分配釋放的位置,用於檢測內存錯誤,或者直接在已有的內存上構造對象,那麼必須定義更多參數,這就需要placement new/delete,聲明如下.

*    ( std::size_t count, **    ( std::size_t count, user-defined-  delete  ( * ptr, *  delete  ( * ptr, user-defined-args...);

可以直接在已有內存上構造對象:

 *mem = (*)malloc(( *j = (mem) (,mem, j, *

運行結果:

mem=0x8a48008, j=0x8a48008, *j = 3

可以看出new直接在mem上面構造了對象。

目前,void* operator new  ( std::size_t count, void* ptr )在全局域還不能被重載,但是void* operator new  ( std::size_t count, user-defined-args... )可以自由定義。

比如記錄內存分配發生的位置:

*    delete( **  (std::size_t size, * filename,  ::   delete( *place, * filename,  *k = (__FILE__, __LINE__) (, k, *

運行結果:

new called at testnew.cpp:41  size=4

operator new called, size=4

k=0x847f008 *k=1

operator delete called

在每個new中打印了文件名和行號,不過細心的你會發現delete時並沒有調用重載的placement delete ,這個delete只有在構造對象時拋出了異常才會調用,我們寫一個簡單的class來看看:

 v):value_(v){  *= (__FILE__, __LINE__) ThrowExcept(( &

運行結果:

new called at testnew.cpp:53  size=4

operator new called, size=4

delete called at testnew.cpp:53  place=0x9e2e008

operator delete called

catch exception 1

自定義的delete被正常調用,這麼做的原因在於如果構造函數拋出異常,系統正常的operator delete並不知道用戶自定義的placement new做了什麼,自然也不知道怎麼去釋放。所以如果自己定義placement new, 一定要定義對應的palcement delete,不然可能出現memory leak。

 

http://en.cppreference.com/w/cpp/memory/new/operator_new

http://en.cppreference.com/w/cpp/language/new

《effective/more effective c++》

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved