36

C では、標準のメモリ処理関数はmalloc()realloc()およびfree()です。ただし、C++ stdlib アロケーターは、それらのうちの 2 つにしか対応していません。再割り当て機能はありません。もちろん、realloc()単純にメモリをコピーすることは非集約型には適していないため、 とまったく同じことはできません。しかし、たとえば、この関数に問題があるでしょうか:

bool reallocate (pointer ptr, size_type num_now, size_type num_requested);

どこ

  • ptrnum_nowオブジェクトに対して同じアロケータで以前に割り当てられています。
  • num_requested>= num_now;

セマンティクスは次のとおりです。

  • アロケーターが特定のメモリ ブロックをオブジェクトptrのサイズからnum_nowオブジェクトに拡張できる場合、アロケータはnum_requestedそれを行い (追加のメモリを初期化せずに残します)、 を返しますtrue
  • それ以外の場合は何もせずに返しますfalse

確かに、これはそれほど単純ではありませんが、私が理解しているように、アロケーターはほとんどがコンテナー用であり、コンテナーのコードは通常、既に複雑になっています。

そのような関数を考えるとstd::vector、たとえば、 は次のように成長する可能性があります (疑似コード):

if (allocator.reallocate (buffer, capacity, new_capacity))
  capacity = new_capacity;     // That's all we need to do
else
  ...   // Do the standard reallocation by using a different buffer,
        // copying data and freeing the current one

メモリ サイズを完全に変更できないアロケータは、無条件でそのような関数を実装できますreturn false;

気にする価値がないほど、再割り当て可能なアロケーターの実装はほとんどありませんか? それとも、私が見落としたいくつかの問題がありますか?

4

5 に答える 5

19

から: http://www.sgi.com/tech/stl/alloc.html

これはおそらく最も疑わしい設計上の決定です。コピーせずに既存のオブジェクトのサイズを変更するか、NULL を返すバージョンの reallocate を提供する方が、おそらくもう少し便利だったでしょう。これにより、コピー コンストラクターを持つオブジェクトに直接役立ちます。また、元のオブジェクトが完全に入力されていない場合に、不要なコピーを回避できたはずです。

残念ながら、これは C ライブラリからの realloc の使用を禁止していました。これにより、多くのアロケータの実装が複雑になり、メモリ デバッグ ツールとのやり取りがより困難になります。したがって、この代替案に反対することにしました。

于 2010-06-23T21:41:26.947 に答える
15

これは実際には Alexandrescu が標準アロケータ (演算子 new[]/delete[] ではなく、std::vector を実装するために使用されていた stl アロケータなど) で指摘する設計上の欠陥です。

realloc は、malloc、memcpy、および free よりも大幅に高速に発生する可能性があります。ただし、実際のメモリ ブロックのサイズは変更できますが、メモリを新しい場所に移動することもできます。後者の場合、メモリ ブロックが非 POD で構成されている場合は、すべてのオブジェクトを破棄し、再割り当て後にコピー構築する必要があります。

可能性としてこれに対応するために標準ライブラリが必要とする主なものは、標準アロケータのパブリック インターフェイスの一部としての再割り当て関数です。std::vector のようなクラスは、デフォルトの実装が新しくサイズ変更されたブロックを malloc し、古いブロックを解放することであっても、確かにそれを使用できます。メモリ内のオブジェクトを破棄およびコピー構築できる関数である必要がありますが、これを行った場合、メモリを不透明な方法で扱うことはできません。そこには少し複雑さがあり、さらにテンプレートの作業が必要になるため、標準ライブラリから除外された可能性があります。

std::vector<...>::reserve では不十分です。コンテナのサイズが予想される別のケースに対処します。本当に可変サイズのリストの場合、realloc ソリューションを使用すると、std::vector のような連続したコンテナーを大幅に高速化できます。特に、メモリ ブロックが移動せずに正常にサイズ変更された realloc ケースに対処できる場合は、copy の呼び出しを省略できます。メモリ内のオブジェクトのコンストラクタとデストラクタ。

于 2010-06-24T09:41:42.087 に答える
8

あなたが求めているのは、本質的に何をするかですvector::reserve。オブジェクトの移動セマンティクスがなければ、コピーと破棄を行わずにメモリを再割り当てしてオブジェクトを移動する方法はありません。

于 2010-06-23T20:05:56.300 に答える
2

C++ のオブジェクト指向の性質と、さまざまな標準コンテナー型が含まれているため、C よりも方向メモリ管理に重点が置かれていないだけだと思います。realloc() が役立つ場合があることに同意します。ですが、代わりにコンテナーを使用することで、結果として得られる機能のほとんどすべてを取得できるため、これを修正するプレッシャーは最小限です。

于 2010-06-23T20:00:56.457 に答える
2

これは神が間違ったことの 1 つだと思いますが、私は怠惰すぎて標準化委員会に手紙を書くことができませんでした。

配列の割り当てには再割り当てが必要です。

p = renew(p) [128];

またはそのようなもの。

于 2010-06-23T19:55:04.973 に答える