26

私はこのコードを持っています..

 CEngineLayer::CEngineLayer(void)
 {
    // Incoming creation of layers. Wrapping all of this in a try/catch block is
    // not helpful if logging of errors will happen.

    logger = new (std::nothrow) CLogger(this);

    if(logger == 0)
    {
     std::bad_alloc exception;
     throw exception;
    }

    videoLayer = new (std::nothrow) CVideoLayer(this);

    if(videoLayer == 0)
    {
     logger->log("Unable to create the video layer!");

     std::bad_alloc exception;
     throw exception;
    }
 }

 IEngineLayer* createEngineLayer(void)
 {
    // Using std::nothrow would be a bad idea here as catching things thrown
    // from the constructor is needed.

    try
    {
     CEngineLayer* newLayer = new CEngineLayer;

     return (IEngineLayer*)newLayer;
    }
    catch(std::bad_alloc& exception)
    {
     // Couldn't allocate enough memory for the engine layer.
     return 0;
    }
 }

関係のない情報のほとんどを省略しましたが、ここで全体像は明らかだと思います。

すべてのレイヤー作成を個別に試行/キャッチし、bad_allocs を再スローする前にログに記録する代わりに、手動で std::bad_alloc をスローしても問題ありませんか?

4

4 に答える 4

47

質問に答えるだけです (誰も答えていないようなので)、C++03 標準ではstd::bad_alloc次のように定義されています。

namespace std {
  class bad_alloc : public exception {
  public:
    bad_alloc() throw();
    bad_alloc(const bad_alloc&) throw();
    bad_alloc& operator=(const bad_alloc&) throw();
    virtual ˜bad_alloc() throw();
    virtual const char* what() const throw();
  };
}

標準では public コンストラクターが定義されているため、コードからコンストラクターを作成してスローしても安全です。(パブリック コピー コンストラクターを持つ任意のオブジェクトをスローできます、IIRC)。

于 2011-05-16T01:52:10.890 に答える
20

その必要はありません。ステートメントのパラメーターなしの形式を使用して、例外throwをキャッチし、ログに記録してから再スローできます。std::bad_alloc

logger = new CLogger(this);
try {
    videoLayer = new CVideoLayer(this);
} catch (std::bad_alloc&) {
    logger->log("Not enough memory to create the video layer.");
    throw;
}

または、loggerスマート ポインターでない場合 (スマート ポインターである必要があります):

logger = new CLogger(this);
try {
    videoLayer = new CVideoLayer(this);
} catch (std::bad_alloc&) {
    logger->log("Not enough memory to create the video layer.");
    delete logger;
    throw;
} catch (...) {
    delete logger;
    throw;
}
于 2010-12-05T06:53:36.363 に答える
5

STLコンテナでカスタムアロケータを使用する場合、私は個人的にスローします。アイデアは、デフォルトの std::allocator として、同じインターフェイス (動作の観点からも含む) を STL ライブラリに提示することです。

したがって、カスタム アロケータ (たとえば、メモリ プールからの割り当て) があり、基になる割り当てが失敗した場合は、"throw std::bad_alloc" を呼び出します。これにより、99.9999% の確率で STL コンテナーである呼び出し元が適切にフィールドされることが保証されます。アロケータが大きな脂肪の 0 を返した場合に、これらの STL 実装が何をするかを制御することはできません。

于 2013-10-18T15:42:19.057 に答える
1

もう 1 つのパターンは、ロガーも RAII の影響を受けるという事実を利用することです。

CEngineLayer::CEngineLayer( )
 {
   CLogger logger(this); // Could throw, but no harm if it does.
   logger.SetIntent("Creating the video layer!");
   videoLayer = new CVideoLayer(this);
   logger.SetSucceeded(); // resets intent, so CLogger::~CLogger() is silent.
 }

複数のステップがある場合、これはきれいにスケーリングします。.SetIntent繰り返し電話するだけです。通常は、最後のインテント文字列のみを書き出しますCLogger::~CLogger()が、さらに詳細なログを記録するために、すべてのインテントを書き出すことができます。

ところで、あなたcreateEngineLayercatch(...). ロガーが ? をスローするとどうなりDiskFullExceptionますか?

于 2011-01-31T14:39:01.467 に答える