2009-11-10 15 views
5

中規模のアプリケーションをCからC++に移植します。それは例外を伴ってどこでも処理しません、そして、それは変わるべきではありません。std :: bad_allocを避けてください。 newはNULLポインタを返します。

私の(間違った!)C++の理解は、(デフォルトの)new演算子が割り当て問題の場合にNULLポインタを返すということでした。しかし、それは1993年(またはそれ以降)までしか真実ではなかった。今日では、std :: bad_alloc例外がスローされます。

すべての呼び出しでstd :: nothrowを使用してすべてを書き直すことなく、古い動作に戻ることはできますか?

+2

この記事を読むことに興味があります:http://stackoverflow.com/questions/550451/will-new-return-null-in-any-case – Naveen

+6

std :: nothrowを使うようにコードを修正してください。 awkといくつかの正規表現があなたの道の90%を得るでしょう。 –

+0

+1私はそのようなことをすることに反対しているにもかかわらず、多くの人々のために実際には実際のものです(そして私はなぜ以下の理由で答えましたか)。 –

答えて

11

あなたは、new演算子をオーバーロードすることができます:

#include <vector> 

void *operator new(size_t pAmount) // throw (std::bad_alloc) 
{ 
    // just forward to the default no-throwing version. 
    return ::operator new(pAmount, std::nothrow); 
} 

int main(void) 
{ 
    typedef std::vector<int> container; 

    container v; 
    v.reserve(v.max_size()); // should fail 
} 
+1

@GMan:この例では、失敗は明確ではありません。nothrowを使用することの欠点を示すことを意図していますか? – stefaanv

+2

これはおそらく致命的に失敗するでしょう。標準コンテナは、allocator(デフォルトでは標準アロケータ)を使用してメモリを処理し、少なくとも1つはメモリがないときに例外がスローされると予想し、NULLの戻り値をチェックしません。 これは、クラスのオーバーロードされた演算子の問題を解決しません。しかし、これはコードがCから移植されていることを考慮に入れては起こりそうな問題ではありません。 –

+0

それは例外なく "正常に"実行されることを意味しました。 Adamのポイントを念頭に置いてください。あなたは基本的に「オペレーター・ニュー」がどのように失敗して動作するかを再考しており、一部の人々はそれに頼っています。しかし、あなたはそれらの一つではありません。 :) – GManNickG

0

あなたのコンパイラは、おそらく無効/この動作を有効にするには、コマンドラインスイッチがあります。

+2

は、はるかに役に立つ答えは、おそらくgccとVC++のために少なくとも存在するコマンドラインスイッチを書くことでした。 –

3

<new>を含めます。

#include <new> 

int main() { 
    int* p = new(std::nothrow) int; 
    if (p) { 
     delete p; 
    } 
} 

編集:私は質問の最後の文を逃し認める それはあなたがこのように使用できる新しいの「ノー・スロー」バージョンが含まれています。しかし、正直言って、「普通のnew」にプレスタンダードの振る舞いを調整するのはいい考えではないと思います。私は&自動検索のいくつかの種類をそれぞれにnewを切り替えるに置き換えます。

+2

あなたは太字の段落を見逃しています。 –

+0

そうだね。私はそれの後半を逃した。 – sellibitze

1

申し訳ありませんが、私の意見としては、これをして古い動作に戻すべきではありません。とにかく例外を避けることはできないからです。

なぜですか?

一時的なものを動的に構築する必要がある初期化コードを呼び出すコンストラクタでクラスを割り当てる必要がある新しい呼び出しについて考えてみましょう。悲しいかな、あなたには例外があります。あなたがstd :: nothrowを使用するかどうかは関係ありません。これは数多くのシナリオの1つに過ぎません。

Scott Meyersの本Effective C++では、詳細については私が覚えている限り説明しました。しかし、私はすべてのケースがレビューされているかどうかはわかりませんが(私はそれらを十分に提案しています)。

+0

私は代入のためだけにコンストラクタを使います。それ以外のものについては、 "bool Init()"メソッドを使用します。 – dmeister

+0

常に変化します。あなたがこのコードのサポートを落として、地球の反対側に移動した後でさえ、起こる可能性があります。私はちょうど私が人々がstd :: nothrowであまりにも多くを信頼するケースの数を見たことを指摘しました。しかし、それは魔法ではありません;-)。 –

1

ちょうどそれを試してみる:

1.Defineあなたはメモリ条件のうち、上の呼び出したい機能。

2.この関数をnew_handler関数に設定します。新しい関数が呼び出されると、この関数が呼び出されます。

+0

私はそれを認識していませんでしたが、標準のドラフトでは、 'new_handler'はa)より多くのメモリを利用できるようにし、返すこと、b)' std :: bad_alloc'または派生した例外を投げる、c)abort() ()。あなたがすることができないことは、スローする代わりに新しいリターン0を作ることです。 – UncleBens

関連する問題