條款49 了解new handle行為

2022-01-22 06:20:45 字數 2363 閱讀 1793

多執行緒下的記憶體管理與單執行緒下是完全不同的,因為heap是乙個可以被全域性改動的資源,所以所有的執行緒都有可能去訪問這一資源,這回導致很多的race_conditions。

當operator new未取得想要的記憶體的時候,會呼叫乙個使用者指定的處理函式,new_handler。 這個函式可以使用set_new_handler來進行指定。

1

namespace

std

當operator new無法滿足記憶體申請條件的時候,其就會不停的呼叫new-handler函式,所以說乙個設計良好的new-handler應該需要滿足下面的要求:

讓更多的記憶體被使用

當當前的handler無法滿足條件的時候,安裝另乙個new-handler.

卸除new_handler,將null指標傳給set_new_handler,,此時operator new 在無法分配記憶體的時候就會丟擲異常

丟擲bad_alloc異常:這樣的異常會被傳播到記憶體的索求處

不返回:呼叫abort或者exit

當需要以不同的方式去處理不同的class記憶體分配失敗的情況的時候,應該為相應的特殊的class提供自己的set_new_handler以及operator_new。這樣operator new會在分配記憶體的時候確保使用class專屬的new_handler替代global的new handler.

乙個widget分配資源的簡單例子:

1

class

newhandlerholder

5 ~newhandlerholder()

6 std::set_new_handler(handler); //

將狀態恢復到之前的狀態

7private:8

new_handler handler;

9 newhandlerholder(const newhandlerholder &); //

禁止這兩種操作

10 newhandlerholder & operator(const newhandlerholder &);

11 };

上面這個就可以被自定義的乙個類所使用了:

1

void * widget::operator

new(std::size_t size) throw

(std::bad_alloc)

2

實際上,可以將上面的newhandlerholder設計成為乙個基類模板,這樣derived_class科技繼承他們需要的set_new_handler以及operator_new,template用於保證每乙個derived_class獲得乙個實體互異的currenthandler成員變數。下為這個模板:

1 template//

這裡的typename t 並未被使用,作用下面會說

2class

newhandlersupport;

10 template11

static

std::new_handler

12 newhandlersupportset_new_handler(std::new_handler p) throw

()13

18 template19

static

void *

20 newhandlersupport::operator

new(std::size_t size) throw

(std::bad_alloc)

21

有了這個模板,那麼為widget提供專屬的set_new_handler以及operator都是很容易的了。繼承上面的模板並特例化就可以了:

1

class widget : public newhandlersupport;

這樣就有了專屬的set_new_handler以及operator new。

上買了的typename t 沒有被使用,實際上也不需要, 這個t的目的只是為了使得不同的繼承自newhandlersupport的子類有著其不同的例項函式。(主要是為了static變數,currenthandler)。t只是用來區分不同的derived_class. (因為上面t例項化成了widget)

還有就是關於nothrow的問題,使用new (std::nothrow) widget不會在new上產生異常,只會返回乙個null指標,但是如果new正常還有可能在構造過程中產生異常,因此依然沒有異常保證。沒事不要用new (std::nothrow) sth;

小結:set_new_handler允許使用者指定乙個函式在記憶體無法分配時呼叫

nothrow new只能保證new不拋異常,構造仍然得不到保證。

條款49中關於new handler行為

當operator new無法滿足某一記憶體分配時,就會丟擲一次。以前它會返回null指標,現在某些舊式編譯器也還這麼做。namespace std new handler是個函式指標,該函式沒有引數也不返回任何東西。set new handler是設定乙個new handler並返回乙個new h...

條款49 盡量讓自己熟悉C 標準庫

1,標準庫的每一樣東西幾乎都在namespace std中,然而世界上有無可計數的c 程式 依賴那些已經使用多年的 準 標準程式庫,例如宣告於,等檔案中的功能。2,解決方法,設計新的頭檔名,給披上std外衣的各個元件使用。1 將原有的c 標頭檔案中的.h擴充套件拿掉,於是變為。如 cin的型別 ba...

條款42 了解typename的雙重意義

條款42 了解typename的雙重意義 includeusing namespace std templatevoid print2nd const c container templatevoid f const c container,不允許使用typename c並不是巢狀 從屬型別名稱,解...