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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

关于placement new 和 placement delete的重载,以及basic_string重载new()实例

發布時間:2023/12/1 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 关于placement new 和 placement delete的重载,以及basic_string重载new()实例 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

關于placement new

在https://blog.csdn.net/qq_42604176/article/details/111997397中已經介紹了placement new的形式。
它的形式為new()/delete().我們將分配好內存的指針送入括號中,就完成了初步的調用了。
其實我們可以定義放任何的東西到()內部。只放一個指針的版本是的new()是標準庫先寫好給我們的。
我們可以重載operator new,并寫出多個版本,如:

Foo* pf = new(300,'c')Foo; //注意,這里沒有傳入指針

前提是每一個版本的聲明都必須由獨特的參數列,其中第一個參數必須是size_t,這是因為當沒有()時,進行的是new Foo操作,Foo的大小會被傳進operator new中作為第一參數,Foo的大小是個size_t類型。所以我們寫的各種各樣的版本也必須遵循這個規則。第二第三參數等等可由自己設計。new()括號中的就是第二第三參數,他們可以指定placement arguments 為初值。
下面是實例:

class Foo { public:Foo() {cout << "Foo::Foo()" << endl; };Foo(int) {cout << "Foo::Foo()" << endl; throw Bad();} //這里故意拋出異常,用來測試 placement operator delete//【1】一般的operator new()的重載void* operator new(size_t size) {return malloc(size);}//【2】這個是標準庫已提供的placement new()的重載形式void* operator new(size_t size, void* start) {return start;}//【3】這個是我們重載的 placement new void* operator new(size_t size, long extra) {return malloc(size + extra);}//【4】這個也是我們重載的 placement newvoid* operator new(size_t size, long extra, char init) {return malloc(size + extra);}//【5】這個也是我們重載的,不過我們故意寫錯定義參數的類型void* operator new(long extra, char init) {return malloc(extra);} //很顯然這個版本會報錯 };

關于placement delete

我們也可以重載placement operator delete,并對應著placement operator new寫出多個對應版本,但他們絕對不會被delete調用。
只有當new所調用的ctor拋出異常,才會調用這些重載版本的operator delete。
也就是說重載的placement operator delete是用來釋放未能成功創建的對象所占的內存。(正如我們所知,創建一個對象實際上是先申請空間,再調用構造函數??臻g申請到了,但是對象卻沒構造出來,那么理所當然需要將空間釋放)
對應上面的四種版本的delete:

//【1】一般的 operator delete()的重載 void operator delete(void*,size_t) {cout << "operator delete(void*,size_t)" << endl; } //【2】對應第二種 void operator delete(void*,void*) {cout << "operator delete(void*,void*)" << endl; } //【3】對應第三種 void operator delete(void*,long) {cout << "operator delete(void*,long)" << endl; } //【4】對應第四種 void operator delete(void*,long,char) {cout << "operator delete(void*,long,char)" << endl; }

侯捷老師給出了下面的示例,運行到第五種。我們可以發現,此時的構造函數調用的是第二種構造函數。在之前的定義中,我們在這里拋出了異常。

接下倆便是這幾條語句的執行結果:

如上所示,這些new都被重載了。所以才會打印信息。
按照道理,在構造函數拋出異常后,會調用自己重載的placement delete,打印信息。但在這里并沒有,這是編譯器的原因。

關于basic_string重載new()來擴充申請量

basic_string是標準庫里面的一個class,就是我們使用的字符串。
如下:

template<...> class basic_string { private:struct Rep {...};...void release() {if(--ref == 0) delete this;}inline static void* operator new(size_t,size_t);inline static void operator delete(void*);inline static Rep* create(size_t);... };

operator new的具體代碼如下:

template<class charT,class traits, class Allocator> inline void* basic_string<charT,traits,Allocator>::Rep:: operator new(size_t s,size_t extra) {return Allocator::allocate(s + extra * sizeof(charT)); }

如何使用看這兒:
這里我們把第二參數叫做extra。它的作用是,當使用者去創建一個字符串,如"hello",加上結束符一共6個字符。但是它在分配的時候還會分配extra個字符大小的空間。具體原因不做細究。

template<class charT,class traits,class Allocator> inline basic_string<charT,traits,Allocator>::Rep* basic_string<charT,traits,Allocator>::Rep:: create(size_t extra) {extra = frob_size(extra + 1);Rep *p = new(extra)Rep;...return p; }

它的placement delete重載之后則長這樣:

template<class charT,class traits,class Allocator> inline void basic_string<charT,traits,Allocator>::Rep:: operator delete(void* ptr) {Allocator::deallocate(ptr,sizeof(Rep) + reinterpret_cast<Rep*>(ptr)->res * sizeof(charT)); }

總結

以上是生活随笔為你收集整理的关于placement new 和 placement delete的重载,以及basic_string重载new()实例的全部內容,希望文章能夠幫你解決所遇到的問題。

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