[翻譯] Effective C++, 3rd Edition, Item 49: 瞭解 new-handler 的行為(下)

來源:互聯網
上載者:User

(點擊此處,接上篇)

但是也許你依然在為 Widget 從 NewHandlerSupport<Widget> 繼承而煩惱。如果是這樣,當你注意到 NewHandlerSupport template 從來沒有用到它的 type parameter T 時,你可能會更加煩惱。它不需要那樣做。我們需要的全部就是為每一個從 NewHandlerSupport 繼承的 class 提供一份不同的 NewHandlerSupport ——特別是它的 static data member(待用資料成員)currentHandler ——的拷貝。template parameter T 只是為了將一個 inheriting class 同另一個區分開來。template 機制自己自動地為每一個被執行個體化的 NewHandlerSupport 中的 T 產生一個 currentHandler 的拷貝。

對於 Widget 從一個把 Widget 當作一個 type parameter(型別參數)的 templatized base class(模板化基類)繼承,如果這個概念把你弄得有點糊塗,不必難受。它最開始對每一個人都有這種影響。然而,它發展成如此有用的一項技術,它有一個名字,雖然它正常看上去所反映的事實並不是他們第一次看到它的樣子。它被稱作 curiously recurring template pattern(奇特的遞迴模板模式) (CRTP)。真的。

在這一點上,我發表了一篇文章建議一個更好的名字叫做 "Do It For Me",因為當 Widget 從 NewHandlerSupport<Widget> 繼承時,它其實是在說:“我是 Widget,而我要從針對 Widget 的 NewHandlerSupport class 繼承。”沒有人使用我提議的名字(甚至是我自己),但是把 CRTP 考慮成說 "do it for me" 的一種方式也許會協助你理解 templatized inheritance(模板化繼承)在做些什麼。

像 NewHandlerSupport 這樣的 templates 使得為任何有需要的 class 添加一個 class-specific new-handler 變得易如反掌。然而,mixin-style inheritance(混合風格繼承)總是會導致 multiple inheritance(多繼承)的話題,而在我們沿著這條路走下去之前,你需要閱讀 Item 40。

直到 1993 年,C++ 還要求 operator new 不能分配被請求的記憶體時要返回 null。operator new 現在則被指定拋出一個 bad_alloc exception,但是很多 C++ 程式是在編譯器開始支援這個修訂標準之前寫成的。C++ 標準化委員會不想遺棄這些 test-for-null(檢驗是否為 null)的代碼基礎,所以他們提供了 operator new 的另一種可選形式,用以提供傳統的 failure-yields-null(失敗導致 null)的行為。這些形式被稱為 "nothrow" 形式,這在一定程度上是因為它們在使用 new 的地方使用了 nothrow objects(定義在標頭檔 <new> 中):

class Widget { ... };
Widget *pw1 = new Widget;                 // throws bad_alloc if
                                          // allocation fails

if (pw1 == 0) ...                         // this test must fail

Widget *pw2 =new (std::nothrow) Widget;   // returns 0 if allocation for
                                          // the Widget fails

if (pw2 == 0) ...                         // this test may succeed

對於異常,nothrow new 提供了比最初看上去更少的強制保證。在運算式 "new (std::nothrow) Widget" 中,發生了兩件事。首先,operator new 的 nothrow 版本被調用來為一個 Widget object 分配足夠的記憶體。如果這個分配失敗,眾所周知,operator new 返回 null pointer。然而,如果它成功了,Widget constructor 被調用,而在此刻,所有打的賭都失效了。Widget constructor 能做任何它想做的事。它可能自己 new 出來一些記憶體,而如果它這樣做了,它並沒有被強迫使用 nothrow new。那麼,雖然在 "new (std::nothrow) Widget" 中調用的 operator new 不會拋出,Widget constructor 卻可以。如果它這樣做了,exception 像往常一樣被傳播。結論?使用 nothrow new 只能保證 operator new 不會拋出,不能保證一個像 "new (std::nothrow) Widget" 這樣的運算式絕不會導致一個 exception。在所有的可能性中,你最好絕不需要 nothrow new。

無論你是使用 "normal"(也就是說,exception-throwing)new,還是它的稍微有些矮小的堂兄弟,理解 new-handler 的行為是很重要的,因為它可以用於兩種形式。

Things to Remember

  • set_new_handler 允許你指定一個當記憶體配置請求不能被滿足時可以被調用的函數。
  • nothrow new 作用有限,因為它僅適用於記憶體配置,隨後的 constructor 調用可能依然會拋出 exceptions。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.