C++ 移行ガイド

例外の指定

古い規則では、割り当てに失敗すると、どの形式の operator new でも NULL ポインタ を返します。新しい規則では、割り当てに失敗すると、通常の形式の operator new では例外を送出し、値は返しません。このほか、例外を送出する代わりにゼロを返す特殊な形式の operator new もあります。どの形式の operator new および operator delete にも、「例外指定」があります。次は、標準ヘッダーの <new> にある宣言です。


namespace std {
    class bad_alloc;
    struct nothrow_t {};
    extern const nothrow_t nothrow;
}
// 単一オブジェクト形式
void* operator new(size_t size) throw(std::bad_alloc);
void* operator new(size_t size, const std::nothrow_t&) throw();
void operator delete(void* ptr) throw();
void operator delete(void* ptr, const std::nothrow_t&) throw();
// 配列形式
void* operator new[](size_t size) throw(std::bad_alloc);
void* operator new[](size_t size, const std::nothrow_t&) throw();
void operator delete[](void* ptr) throw();
void operator delete[](void* ptr, const std::nothrow_t&) throw();

次の例に示すような安全対策のためのコードは、新しい規則では意図したとおりには動作しません。割り当てに失敗すると、new 式から自動的に呼び出される operator new によって例外が送出され、ゼロを判定する検査は行われません。


T* p = new T;
if( p == 0 ) {           // 新しい規則ではエラー
    ...                  // 割り当て失敗の処理
}
...                      // pを使用する

このような場合には、次の 2 つの方法で解決できます。

コード中で例外を使用したくない場合は、2 番目の形式を使用してください。コード中で例外を使用するときは、最初の形式をお勧めします。

operator new が成功するかどうかを確認していない場合は、既存のコードを変更せずにそのまま使用してもかまいません。不正なメモリー参照が発生する箇所まで処理が進むことはなく、プログラムは割り当てに失敗した時点で異常終了します。