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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

Effective C++ 读书笔记(八)

發(fā)布時(shí)間:2023/12/13 c/c++ 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Effective C++ 读书笔记(八) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

8 定制new和delete

條款49:了解new-handler的行為

new_handler ?set_new_handler (new_handler new_p) ?throw();

Sets ?new_p ?as the new handler function, ?the old one is returned.

operator new拋出異常以反映一個未獲滿足的內(nèi)存需求之前,它會先調(diào)用一個客戶指定的錯誤處理函數(shù),客戶必須調(diào)用set_new_handler設(shè)定。

class NewHandlerHolder{

explicit NewHandlerHolder (std::new_handler? nh):handler(nh){}

~NewHandlerHolder(){std::set_new_handler(handler);}

private:

???????? std::new_handler? handler;

};

?

class Widget{

public:

???????? static? std::new_handler set_new_handler(std::new_handler? p) throw();

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

private:

???????? static? std::new_handler? currentHandler;

};

std::new_handler ?Widget::currentHandler = 0;

std::new_handler? Widget::set_new_handler (std::new_handler? p) throw

{

std::new_handler? oldHandler = currentHandler;

currentHandler? = p;

return oldHandler;

}

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

{

NewHandlerHolder h( std::set_new_handler(currentHandler) );

return ::operator new(size);

}

?

使用:

void outOfMem();

Widget::set_new_handler(outOfMem);

Widget* pw1 = new Widget;

?

條款50:了解new和delete的合理替換時(shí)機(jī)

條款51:編寫new和delete時(shí)需固守常規(guī)

實(shí)現(xiàn)一致性operator new必得返回正確的值,內(nèi)存不足時(shí)必得調(diào)用new-handling函數(shù),必須有對付0內(nèi)存需求的準(zhǔn)備。operator new返回值十分單純,如果它有能力供應(yīng)客戶申請的內(nèi)存,就返回一個指針指向那塊內(nèi)存,如果沒有那個能力,拋出一個bad_alloc異常。

???????? 然而也不是非常單純,因?yàn)閛perator new實(shí)際上不只一次嘗試分配內(nèi)存,并在每次失敗后調(diào)用new-handling函數(shù)。這里假設(shè)new-handling函數(shù)能夠做某些動作將內(nèi)存釋放出來,只有當(dāng)new-handling指針為null時(shí),operator new才會拋出異常。

下面是non-member operator new?偽碼:

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

{

???????? using namespace std;

???????? if(size == 0) size =1;

???????? while(true){

???????? 嘗試分配size bytes;

???????? if 分配成功

?????????????????? return 一個指針指向分配的內(nèi)存

???????? new_handler? globalHandler? =? set_new_handler(0);

???????? set_new_handler( globalHandler);

???????? if( globalHandler ) (*globalHandler)();

???????? else throw std::bad_alloc();

}

}

?

許多人沒有考慮operator new成員函數(shù)會被derived class繼承。一旦被繼承base class的operator new被調(diào)用以分配derived class對象。例如:

class Base{

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

???????? …

}

class Derived: public Base { … }

Derived* p = new Derived; //調(diào)用Base::operator new

解決方法:

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

{

???????? if(size != sizeof(Base) ) return ::operator new(size);

???????? …

}

?

條款52:寫了placement new也要寫placement delete

如果operator new接受的參數(shù)除了一定會有的那個size_t之外還有其他,這便是所謂的placement new。眾多placement new版本中特別有用的一個是“接受一個指針指向?qū)ο笤摫粯?gòu)造之處”,那樣的operator new聲明如下:

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

對于以下代碼:

class Widget{

public:

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

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

???????? …

};

上述代碼存在微妙的內(nèi)存泄漏。它在動態(tài)創(chuàng)建一個Widget時(shí)將相關(guān)分配信息志記于cerr:

???????? Widget* pw = new (std::cerr) Widget;

如果內(nèi)存分配成功,但Widget構(gòu)造函數(shù)拋出異常,運(yùn)行系統(tǒng)有責(zé)任取消operator new的分配。運(yùn)行系統(tǒng)會尋找參數(shù)個數(shù)和類型都 與operator new相同 的某個operator delete,如果找到,那就是它的調(diào)用對象。

class Widget{

public:

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

???????? static void? operator delete(std::size_t size, std::ostream& logStream)throw( );

static void? operator delete(void* pMemory) throw( );

???????? …

};

Widget* pw = new (std::cerr) Widget; //不再泄漏

但 delete pw;//調(diào)用正常的operator delete,而非 placement版本。

因此,我們必須同時(shí)提供一個正常的operator delete和一個placement版本(參數(shù)必須和operator new一樣)。只要這樣做,就不會有難以察覺的內(nèi)存泄漏了。

?

另外,考慮到成員函數(shù)的名稱會掩蓋其外因作用域中的相同名稱,例如:

class Base{

public:

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

???????? …

};

Base* pb = new Base; //error,掩蓋

Base* pb = new (std::cerr) Base; //OK

同理,derived classes 中的operator new掩蓋global版本和繼承版。

class Derived: public Base{

public:

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

???????? …

};

Derived* pd = new (std::clog) Derived; //error,掩蓋

Derived* pd = new Derived;

解決辦法:建立一個base class,內(nèi)含所有正常形式的new 和 delete。

?

若想以自定義形式擴(kuò)展標(biāo)準(zhǔn)形式的客戶,可利用繼承機(jī)制及using聲明式取得標(biāo)準(zhǔn)形式。

?

轉(zhuǎn)載于:https://www.cnblogs.com/dachengxu/archive/2012/11/21/2781669.html

總結(jié)

以上是生活随笔為你收集整理的Effective C++ 读书笔记(八)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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