4

Exceptional C++ では、Herb Sutter が項目 35 でガイドラインとして次のように書いています。

無料ストア (新規/削除) を使用することをお勧めします。ヒープ (malloc/free) を使用しないでください。

どして私がこんな事に?

new実装が を使用して実装することを選択した場合、mallocおそらくオーバーヘッドが発生するため、パフォーマンスに関する限り、これは悪いアドバイスのように見えます。

4

1 に答える 1

11

C++のnewanddeleteキーワードは通常、mallocandの観点から実装されfreeますが、異なることを行うように設計されています。

C++ で言うと、

new T(/* args */)

C++ は次のことを行います。

  • タイプ のオブジェクトを保持するのに十分なメモリを割り当てようとしますT
  • 失敗した場合は、新しいハンドラを使用して領域を解放しようとし、std::bad_allocメモリが利用できない場合は最終的にオブジェクトをスローします。
  • Tそのメモリ ブロックで型のオブジェクトの構築を試みます。
  • 型のオブジェクトの構築でT例外がスローされた場合、メモリの割り当てを自動的に解除します。

を使用するだけの場合malloc、これらの手順をすべて手動で行う必要があり、非常に困難です。次のようになります。

T* memory = nullptr;
while (true) {
   memory = static_cast<T*>(malloc(sizeof(T)));
   if (memory != nullptr) break;

   std::get_new_handler()();  
}

try {
    new (memory) T(/* args */);
} catch (...) {
    free(memory);
    throw;
}

ここで私が見落としたニュアンスが他にもいくつかあります ( のoperator new代わりに呼び出すmalloc、サイズがゼロのリクエストを処理するなど) が、newmallocがどのように異なるかを説明するのに役立つことを願っています。

では、なぜnewoverを使用する必要があるのmallocでしょうか。いくつかの理由があります。

  • はるかに安全です。 null ポインターの戻り値の型をチェックするのをmalloc忘れたり、間違った量のストレージ スペースを要求したり、オブジェクトでコンストラクターを呼び出すのを忘れたり、コンストラクターが例外をスローした場合にメモリの割り当てを解除するのを忘れたりする可能性があります。など

  • より型安全です。 mallocを返しますvoid*。これはメモリ ブロックへの単なるポインタです。を使用mallocすると、ポインターを適切な型にキャストする必要があり、後でエラーが発生する可能性があります。

  • カスタマイズが可能です。 特定の型はオーバーロードoperator newして、プールされたアロケーターやより高速なメモリの特定の部分から、または使用パターンを最適化するカスタム アロケーターを使用するなど、通常とは異なる方法でメモリを要求します。これにより、とTを定義するだけで、タイプのオブジェクトにメモリが動的に割り当てられるすべての時間を自動的にカスタマイズできます。を使用する場合は、プログラム全体ですべてのメモリ割り当てサイトを追跡する必要があります。operator newoperator deletemalloc

とはいえ、 にはいくつかの利点がありmallocます。自明なオブジェクト (データを保持するだけのプリミティブや構造体など) であるオブジェクトを割り当てていることが確実にわかっている場合は、malloc. mallocも使用できますがrealloc、使用できfreeません。std::vectorしかし、正直なところ、このような場合は単にorを使用したほうがよいでしょう。std::arrayなぜなら、それらはより安全で、デバッグが容易であり、適切なコンパイラ サポートがあれば、積極的に最適化される可能性が高いからです。

お役に立てれば!

于 2013-05-06T18:31:35.627 に答える