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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

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

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

關(guān)于placement new

在https://blog.csdn.net/qq_42604176/article/details/111997397中已經(jīng)介紹了placement new的形式。
它的形式為new()/delete().我們將分配好內(nèi)存的指針?biāo)腿肜ㄌ?hào)中,就完成了初步的調(diào)用了。
其實(shí)我們可以定義放任何的東西到()內(nèi)部。只放一個(gè)指針的版本是的new()是標(biāo)準(zhǔn)庫先寫好給我們的。
我們可以重載operator new,并寫出多個(gè)版本,如:

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

前提是每一個(gè)版本的聲明都必須由獨(dú)特的參數(shù)列,其中第一個(gè)參數(shù)必須是size_t,這是因?yàn)楫?dāng)沒有()時(shí),進(jìn)行的是new Foo操作,Foo的大小會(huì)被傳進(jìn)operator new中作為第一參數(shù),Foo的大小是個(gè)size_t類型。所以我們寫的各種各樣的版本也必須遵循這個(gè)規(guī)則。第二第三參數(shù)等等可由自己設(shè)計(jì)。new()括號(hào)中的就是第二第三參數(shù),他們可以指定placement arguments 為初值。
下面是實(shí)例:

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】這個(gè)是標(biāo)準(zhǔn)庫已提供的placement new()的重載形式void* operator new(size_t size, void* start) {return start;}//【3】這個(gè)是我們重載的 placement new void* operator new(size_t size, long extra) {return malloc(size + extra);}//【4】這個(gè)也是我們重載的 placement newvoid* operator new(size_t size, long extra, char init) {return malloc(size + extra);}//【5】這個(gè)也是我們重載的,不過我們故意寫錯(cuò)定義參數(shù)的類型void* operator new(long extra, char init) {return malloc(extra);} //很顯然這個(gè)版本會(huì)報(bào)錯(cuò) };

關(guān)于placement delete

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

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

侯捷老師給出了下面的示例,運(yùn)行到第五種。我們可以發(fā)現(xiàn),此時(shí)的構(gòu)造函數(shù)調(diào)用的是第二種構(gòu)造函數(shù)。在之前的定義中,我們在這里拋出了異常。

接下倆便是這幾條語句的執(zhí)行結(jié)果:

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

關(guān)于basic_string重載new()來擴(kuò)充申請量

basic_string是標(biāo)準(zhǔn)庫里面的一個(gè)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)); }

如何使用看這兒:
這里我們把第二參數(shù)叫做extra。它的作用是,當(dāng)使用者去創(chuàng)建一個(gè)字符串,如"hello",加上結(jié)束符一共6個(gè)字符。但是它在分配的時(shí)候還會(huì)分配extra個(gè)字符大小的空間。具體原因不做細(xì)究。

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)); }

總結(jié)

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

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。