1

インターフェイスの一部であるため、生のポインターをスマート ポインターに変更できないケースがあります (それを使用するコードを壊したくありません)。

struct Foo
{
  Foo();
  ~Foo();

  int * m_pStuff; // public!
};

私は自分のセンターで多くのことをしたくありません。次のようなものです:

m_pStuff = new int[dynamically_obtained_size_which_is_greater_than_0];
m_pStuff[0] = 0;

そして、デストラクタでそれを削除します。

ここで、try/catch で囲む価値があるかどうか疑問に思います。

Foo::Foo()
  : m_pStuff(0)
{
  try
  {
    m_pStuff = new int[dynamically_obtained_size_which_is_greater_than_0];
    m_pStuff[0] = 0;
  } 
  catch(...)
  {
    delete m_pStuff;
    throw;
  }
}

私が見ることができるポイント:

  • より複雑なコード
  • そこで例外が発生することを実際には期待していません(割り当て時にスペースが不足しない限り)
  • コードが変更されることを本当に期待していない

私が見ることができるポイント:

  • 潜在的な将来のコーダーに、例外をスローするものに注意し、それを既に配置されている try ブロックに入れる必要があることを示します
  • 例外が発生した場合、メモリ解放が処理されます

私はかなり未定です: これを try/catch で囲む必要がありますか? なんで?その上でご意見をお聞きしたいです。

また、割り当て時にメモリ不足が原因で発生する以外の例外の可能性はありますか? その場合、すでに割り当てられているメモリは自動的に再利用されますよね?

ありがとう!

4

3 に答える 3

5

いいえ。

まったく無意味です。

int構築はスローしない可能性があるため、ここで考えられる唯一の例外はstd::bad_alloc. この場合、あなたは何をしていますか?

  • まずdelete、何もしない NULL ポインターを使用しています。割り当てが失敗したため、何も「回収」していません。
  • 次に、例外を再スローしています。

tryつまり、 /なしで正確に何が起こるかcatch

例外を伝播させ、それが可能であることを文書化してください。

ただし、このアドバイスは必ずしも他のタイプには当てはまりません。


また、コピー コンストラクターも忘れないでください。

于 2013-04-16T13:32:40.337 に答える
0

ただの追加情報

コンストラクターから例外をスローすることは、潜在的に悪い考えです。コードを見てください

class Foo
{
    Foo(int* a, int* b): _a(a), _b(b)
    {

    }

public:
    Foo() :
        Foo(nullptr, nullptr)
        // _a(nullptr), _b(nullptr)
    {
        _a = new int[10];
        _b = new int[100500 * 100500]; // should throw an exception
    }

    ~Foo()
    {
        delete[] _a;
        delete[] _b;

        std::cout << "~Foo()" << std::endl;
    }

private:
    int* _a;
    int* _b;
};

int main()
{
    try
    {
        Foo f;
    }
    catch(std::exception& e)
    {
        std::cout << "Catched: " << e.what() << std::endl;
    }
}

このコードは期待どおりに機能します。

~Foo()
キャッチ: std::bad_alloc

しかし、Foo(nullptr, nullptr)行をコメントして行のコメントを外す// _a(nullptr), _b(nullptr)と、次の出力が表示されます。

キャッチ: std::bad_alloc

オブジェクトが完全に構築されていないため、新しいコードは destrutor を呼び出しません。メモリ リークがあります。

それを避けるためにあなたは何をすべきですか?

  • 生のポインタを使用しないでください。代わりにスマート ポインタを使用してください。
  • 最初の例のように、あるコンストラクターを別のコンストラクターにカプセル化します。
于 2013-04-16T14:01:27.303 に答える
0

この場合、新しいポインターで std::bad_alloc を取得すると NULL になり、何もしない NULL の削除につながるため、try catch は必要ありません。

于 2013-04-16T13:33:05.433 に答える