日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C++ new/new operator、operator new、placement new初识

發布時間:2023/12/1 c/c++ 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++ new/new operator、operator new、placement new初识 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

簡要釋義

1.operator new是內存分配函數(同malloc),C++在全局作用域(global scope)內提供了3份默認的operator new實現,并且用戶可以重載operator new。

1 void* operator new(std::size_t) throw(std::bad_alloc);//normal new 2 void* operator new(std::size_t,const std::nothrow_t&) throw();//nothrow new 3 void* operator new(std::size_t,void*) throw();//placement new

下面這兩行代碼是等價的,都是分配一塊大小為sizeof(widget)的內存并返回指針,沒有執行構造函數

1 widget *a=(widget*) ::operator new(sizeof(widget)); 2 widget *b=(widget*)malloc(sizeof(widget));

2.new/new operator即C++內置的new操作符。

//這里new一個widget對象分成兩步 //1.運行期系統調用operator new開辟sizeof(widget)大小的內存 //2.在該內存地址上構造一個widget對象 widget *c=new widget();

我們平常的new操作由運行期系統調用operator new,然后調用構造函數初始化。這個過程是不可重定義的。即程序員不能重載C++內建的new操作符。我們能重載的僅是其中的 operator new/operator new[],即分配內存的部分。

3.placement new是operator new在全局作用域上的一個重載版本,即如上我們看到的

1 void* operator new(std::size_t,void*) throw();//placement new

?placement new并不分配內存,而是返回已分配的內存的指針,這個指針正是函數參數列表中的void *,即“返回一個你剛傳入的已分配的內存的指針”。

std::中該函數的實現:

1 inline _LIBCPP_INLINE_VISIBILITY void* operator new (std::size_t, void* __p) _NOEXCEPT {return __p;}

?那么為什么需要這個placement new呢?

答案是:當你需要在一段已分配的內存中構造對象時,調用尋常的new widget()會開辟另外一個內存空間,而非在已知地址上構造widget()對象。

//這里先申請了一段內存空間,由指針widget*a持有,并未調用構造函數 //然后用placement new在a地址上構造了widget對象 //這里::表示調用在global scope中的匹配函數 widget *a=(widget*) ::operator new(sizeof(widget)); ::new(a) widget();

?

進一步的討論

1.placement new實質上是有額外實參之operator new,一般情況下我們指的placement new是那個額外實參為void*的重載版本(已被納入C++標準程序庫),這些叫法對我們的討論沒有影響,只要知道placement new同時也是一種operator new即可。但是不要忘了我們可以重載其它版本的placement new,例如額外實參為std::ostream&,提供log功能。

1 #include <iostream> 2 class widget 3 { 4 public: 5 static void * operator new(std::size_t _size,std::ostream& o) 6 { 7 o<<"void * operator new(std::size_t _size,ostream& o)"<<std::endl; 8 return ::operator new(_size); 9 } 10 widget() 11 { 12 std::cout<<"widget()"<<std::endl; 13 }; 14 ~widget() 15 { 16 std::cout<<"~widget()"<<std::endl; 17 }; 18 19 }; 20 int main() 21 { 22 //下面兩種構造方法是等價的 23 //構造一個widget對象,并且使用有log功能的operator new 24 widget* a=(widget*) widget::operator new(sizeof(widget), std::cout); 25 ::new(a) widget(); 26 27 //同樣構造一個widget對象,并且使用有log功能的operator new 28 widget* b=new(std::cout) widget(); 29 return 0; 30 }

?

這份示例代碼中,我在類中重載了placement new,附帶的額外參數是ostream&。

?

2.注意作用域遮掩問題。如果你在類內重載了一個operator new,當你對這個類及其子類使用new操作符的時候,會掩蓋全局作用域中的operator new,編譯器發現里層作用域(類內)有operator new聲明,就不會查找全局作用域是否有其它operator new聲明,而是直接進入參數匹配階段,如果你重載的operator new參數和調用的不匹配,便會拋出一個編譯錯誤。

解決方法就是:如果類內重載了operator new,并且你仍有可能使用到全局作用域中的operator new,請同時也重載和全局作用域同型的operator new,確保調用成功。

為你的類建立一個base class,內含全局作用域同型的operator new,使其調用全局作用域內的operator new即可。

1 #include <iostream> 2 class globalScopeNew 3 { 4 public: 5 static void* operator new(std::size_t size) throw(std::bad_alloc) 6 { 7 return ::operator new(size); 8 } 9 static void* operator new(std::size_t size,const std::nothrow_t& t) throw() 10 { 11 return ::operator new(size, t); 12 } 13 static void* operator new(std::size_t size,void* p) throw() 14 { 15 return ::operator new(size, p); 16 } 17 18 }; 19 class widget:public globalScopeNew 20 { 21 public: 22 using globalScopeNew::operator new; 23 static void * operator new(std::size_t _size,std::ostream& o) 24 { 25 o<<"void * operator new(std::size_t _size,ostream& o)"<<std::endl; 26 return ::operator new(_size); 27 } 28 widget() 29 { 30 std::cout<<"widget()"<<std::endl; 31 }; 32 ~widget() 33 { 34 std::cout<<"~widget()"<<std::endl; 35 }; 36 37 }; 38 int main() 39 { 40 widget* w2=new(std::cout) widget(); 41 //這句調用原來不能通過編譯 42 widget* w1=new widget(); 43 widget* w3=(widget*)operator new(sizeof(widget)); 44 //這句調用原來不能通過編譯 45 new(w3) widget(); 46 return 0; 47 }

?

注意,這邊需要在子類中using globalScopeNew::operator new;即在子類中使基類的operator new可見。

這樣,各種形式的new操作符調用都能通過編譯了。

轉載于:https://www.cnblogs.com/kyokuhuang/p/4199724.html

總結

以上是生活随笔為你收集整理的C++ new/new operator、operator new、placement new初识的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。