5

クラスのコンストラクターがメモリを割り当てる必要があるという問題に遭遇しました。だから私は喜んで書いchar *mem = static_cast<char*>(malloc(100*sizeof(*mem)));た。しかし、エラーが発生した場合にエラーコードを返せないことに突然気付きました(コードで例外を使用していません)。どうすればこの問題を解決できますか?

次のように、メンバーを追加bool initializedし、クラスを作成してすぐに確認する必要があります。

myClass mc;
if (!mc.initialized) {
    printf("Memory allocation failed in mc's constructor\n");
    exit(1);
}

ありがとう、ボダ・シド。

4

4 に答える 4

10

malloc ではなく、new を使用する必要があります。メモリ不足の場合、 new は std::bad_alloc をスローします。割り当てに失敗した場合 (またはその他の理由で初期化に問題がある場合) は、コンストラクタから例外を伝播する必要があります。これが、デストラクタの呼び出しを防ぐ唯一の方法だからです。コンストラクターが正常に完了した場合は、デストラクターを呼び出す必要があります (もちろん、ヒープが割り当てられ、解放されていない場合は除きます)。

于 2010-07-05T01:55:21.350 に答える
5

それが例外が発明された理由です。また、newの代わりに使用しmalloc(3)ます。

于 2010-07-05T01:52:39.703 に答える
3

例外を使用していない場合は、コンストラクターを使用しないでください (または失敗する可能性のあるコンストラクターを記述しないでください)。代わりにファクトリ関数を使用し、それを使用して、失敗する可能性のあるビットを失敗する可能性のあるビットから切り離すことができます

class myClass {
  private:
  char *m_malloced_buffer;

  // disallow calling ctors/dtors directly
  myClass(char *malloced_buffer) : m_malloced_buffer(malloced_buffer) {}
  ~myClass() { free(m_malloced_buffer); }

  public:
  static myClass *create()
  {
     char *buf = static_cast<char*>(malloc(100*sizeof(*mem)));
     if(!buf) return NULL;

     void *myClassRes = malloc(sizeof(myClass));
     if(!myClassRes) return NULL;
     new (myClassRes) myClass(buf); // placement new, uses existing memory to invoke the ctor
     return static_cast<myClass*>(myClassRes);
  }
  static void destroy(myClass* val)
  {
     if(!val) return;
     val->~myClass(); // explicitly invoke dtor
     free(val); // deallocate memory
  }
};
...
myClass *val = myClass::create();
if(val) { ... }
myClass::destroy(val);

この例では、malloc と free を使用してすべての割り当てを行いましたが、new (std::nothrow) と delete を同じように簡単に使用できます。例外を使用せずにエラーをチェックできるように、ctor からファクトリ関数に失敗する可能性のあるすべての操作を抽出する必要があります。この単純な例でさえ、これが首の大きな痛みであることがわかります。コメントで「例外は適切なコーディング スタイルではない」ことを学んだとおっしゃいますが、それを学んだということですか (理由のある議論と説明を伴う指示によるか、経験からか)、または誰かが「例外は適切なコーディング スタイルではない」と言いました。あなたはその声明をドグマとして受け入れましたか?

bool で初期化されたメンバーを使用すると、ゾンビ オブジェクトの問題が発生します ( http://www.parashift.com/c++-faq-lite/exceptions.htmlを参照)。

于 2010-07-05T02:21:51.303 に答える
2

C ではなく C++ を使用している場合は、malloc の代わりに new を使用する必要があります。例外をスローすることは、おそらくコンストラクター内から実行したいことです。

ただし、例外が必要ないために new (nothrow) を使用している場合、または malloc を使用している場合は、NULL に対して返されるポインターを簡単にテストできます。次に、オブジェクトが失敗した状態であることを示すメンバー変数を設定します。これは、標準 C++ ライブラリのストリーム クラスで見られます。

于 2010-07-05T01:52:50.980 に答える