web-dev-qa-db-ja.com

プリミティブのMallocとNew

C++でnewに対してmallocを使用するメリットを理解しています。しかし、プリミティブデータタイプ(非配列)-intfloatなどの特定のケースでは、mallocを使用する方がnewよりも高速ですか?

ただし、プリミティブの場合でもnewを使用することをお勧めしますが、delete[]を使用できるように配列を割り当てる場合は、.

しかし、配列以外の割り当ての場合、intのコンストラクター呼び出しはないと思います。 new演算子はメモリを割り当て、割り当てられているかどうかを確認してからコンストラクタを呼び出します。しかし、プリミティブの配列以外のヒープ割り当てについては、mallocよりもnewを使用する方が良いですか?

お知らせ下さい。

25
Rajeev Mehta

C++ではmallocを使用しないでください。低レベルのメモリ管理プリミティブを実装しているのでない限り、newを使用しないでください。

推奨事項は次のとおりです。

  • 自問してみてください: "動的メモリ割り当てが必要ですか?"。多くの場合、あなたはそれを必要としないかもしれません-ポインタよりもvaluesを好み、スタックを使用してみてください。

  • 動的なメモリ割り当てが必要な場合は、「割り当てられたメモリ/オブジェクトを誰が所有するか」を自問してください。

    • 単一の所有者のみが必要な場合(これは非常に可能性があります)_std::unique_ptr_ を使用する必要があります。これは、new/deleteをゼロコストで抽象化したものです。 (別のデアロケーターを指定できます。)

    • 所有権を共有する必要がある場合は、 _std::shared_ptr_ を使用する必要があります。これは、アトミック操作と追加の「制御ブロック」を使用してすべての所有者を追跡するため、ゼロコストの抽象化ではありません


特に配列を扱う場合、標準ライブラリは手動のメモリ管理を必要としない2つの強力で安全な抽象化を提供します。

_std::array_および_std::vector_は、「配列の必要性」の99%をカバーする必要があります。


さらに重要なこと:標準ライブラリは _std::make_unique__std::make_shared_ を提供しますが、これはalwaysスマートポインタインスタンスを作成するために使用されます。いくつかの理由があります。

  • より短い-Tを繰り返す必要はありません(例:_std::unique_ptr<T>{new T}_)newを使用する必要はありません。

  • より安全な例外。これらは、関数呼び出しでの評価の明確な順序の欠如によって引き起こされる潜在的なメモリリークを防ぎます。例えば。

    _f(std::shared_ptr<int>(new int(42)), g())
    _

    次の順序で評価できます:

    1. new int(42)
    2. g()
    3. ...

    g()がスローすると、intがリークします。

  • (実行時の速度に関して)より効率的です。これは_std::make_shared_にのみ適用されます。_std::shared_ptr_の代わりにこれを使用すると、実装はオブジェクトと制御ブロックの両方に対して単一の割り当てを実行できます。

詳細については この質問 を参照してください。

84
Vittorio Romeo

常にnewを使用することをお勧めします。 mallocを使用する場合でも、スペースが割り当てられているかどうかを手動で確認する必要があります。

最新のc ++では、スマートポインターを使用できます。 make_uniqueおよびmake_sharednewを明示的に呼び出すことはありません。 std::unique_ptrは基礎となるポインタより大きくなく、それを使用するオーバーヘッドは最小限です。

8
Petar Velev

"newまたはmallocを使用する必要がありますか?に対する答えは単一の責任ルールです。

リソース管理は、それを唯一の目的とするタイプで行う必要があります。
これらのクラスはすでに存在します。たとえば、unique_ptrvectorなどです。

mallocまたはnewを直接使用することは、主要な罪です。

6
sp2danny

zwolの答え は正しい正解の答えを既に提供しています:Cインターフェースと相互作用するときはmalloc()/free()を使用してくださいonly
これらの詳細を繰り返すつもりはありません。パフォーマンスの質問に答えます。

真実は、malloc()newのパフォーマンスは異なる可能性があり、実際には異なるということです。 newを使用して割り当てを実行すると、メモリは通常、operator new()とは異なるグローバルmalloc()関数の呼び出しを介して割り当てられます。 operator new()を呼び出してmalloc()を実装するのは簡単ですが、これは必ずしも行われるとは限りません。

実際のところ、operator new()を呼び出すmalloc()operator new()の標準実装よりも約100 CPUサイクル優れているシステムを見てきました。コールごと。これは確かに測定可能な違いであり、標準の実装がmalloc()とは非常に異なる何かを行うことを明確に示しています。

したがって、パフォーマンスが心配な場合は、次の3つのことを行う必要があります。

  1. パフォーマンスを測定します。

  2. グローバルoperator new()関数とそのフレンドの代替実装を記述します。

  3. パフォーマンスを測定して比較します。

利益/損失は重要な場合とそうでない場合があります。