多執行緒下的記憶體管理與單執行緒下是完全不同的,因為heap是乙個可以被全域性改動的資源,所以所有的執行緒都有可能去訪問這一資源,這回導致很多的race_conditions。
當operator new未取得想要的記憶體的時候,會呼叫乙個使用者指定的處理函式,new_handler。 這個函式可以使用set_new_handler來進行指定。
1namespace
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分配資源的簡單例子:
1class
newhandlerholder
5 ~newhandlerholder()
6 std::set_new_handler(handler); //
將狀態恢復到之前的狀態
7private:8
new_handler handler;
9 newhandlerholder(const newhandlerholder &); //
禁止這兩種操作
10 newhandlerholder & operator(const newhandlerholder &);
11 };
上面這個就可以被自定義的乙個類所使用了:
1void * 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都是很容易的了。繼承上面的模板並特例化就可以了:
1class 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並不是巢狀 從屬型別名稱,解...