古い規則では、割り当てに失敗すると、どの形式の 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 つの方法で解決できます。
以下のように、コードを記述し直して例外を捕獲できるようにする。
T* p = 0; try { p = new T; } catch( std::bad_alloc& ) { ... // 割り当て失敗の処理 } ... // pを使用する
コード中で例外を使用したくない場合は、2 番目の形式を使用してください。コード中で例外を使用するときは、最初の形式をお勧めします。
operator new が成功するかどうかを確認していない場合は、既存のコードを変更せずにそのまま使用してもかまいません。不正なメモリー参照が発生する箇所まで処理が進むことはなく、プログラムは割り当てに失敗した時点で異常終了します。