13

私はC ++にはかなり慣れていませんが、 std::string クラスでできるようにメモリを無意味に使用することはできないことを知っています。例えば:

std::string f = "asdf";
f += "fdsa";

文字列クラスは、大きくなったり小さくなったりするのをどのように処理しますか? デフォルトの量のメモリを割り当て、さらに必要な場合は、newより大きなメモリ ブロックを割り当てて、そのメモリに自身をコピーすると仮定します。しかし、サイズ変更が必要になるたびに文字列全体をコピーしなければならないのは、かなり非効率的ではないでしょうか? 私はそれができる別の方法を本当に考えることはできません(しかし明らかに誰かがそうしました)。

さらに言えば、vector、queue、stack などのすべての stdlib クラスは、どのようにして成長と縮小をそれほど透過的に処理するのでしょうか?

4

3 に答える 3

8

あなたの分析は正しいです。サイズ変更が必要になるたびに文字列をコピーするのは非効率的です。そのため、一般的なアドバイスではパターンの使用を思いとどまらせます。文字列の関数を使用して、格納しようとreserveしているものに十分なメモリを割り当てるように要求します。その後、さらに操作を行うと、そのメモリがいっぱいになります。(ただし、ヒントが小さすぎることが判明した場合でも、文字列は自動的に拡張されます。)

コンテナは通常、必要以上のメモリを割り当てることで、頻繁な再割り当ての影響を軽減しようとします。一般的なアルゴリズムは、文字列がスペース不足を検出すると、新しい値を保持するために必要な最小値を割り当てるのではなく、バッファー サイズを2 倍にするというものです。文字列が一度に 1 文字ずつ成長している場合、この 2 倍のアルゴリズムは、時間の複雑さを (2 次時間ではなく) 償却線形時間に減らします。また、メモリの断片化に対するプログラムの脆弱性も軽減されます。

于 2010-08-24T14:50:54.183 に答える
8

通常、倍加アルゴリズムがあります。つまり、現在のバッファーがいっぱいになると、2 倍の大きさの新しいバッファーが割り当てられ、現在のデータがコピーされます。これにより、割り当てブロックを 1 つ増やす方法よりも割り当て/コピー操作が少なくなります。

于 2010-08-24T14:36:37.887 に答える
3

std :: stringの正確な実装はわかりませんが、動的なメモリの増加を処理する必要があるほとんどのデータ構造は、あなたが言うことを正確に実行することによってそれを行います-デフォルトのメモリ量を割り当て、さらに必要な場合は、より大きなブロックを作成します自分をコピーします。

明らかな非効率性の問題を回避する方法は、必要以上のメモリを割り当てることです。ベクトル/文字列/リストなどの使用済みメモリ:合計メモリの比率は、負荷率と呼ばれることがよくあります(わずかに異なる意味でハッシュテーブルにも使用されます)。通常、これは1:2の比率です。つまり、必要なメモリの2倍を割り当てます。スペースが不足した場合は、現在の2倍の量の新しいメモリを割り当てて使用します。これは、時間の経過とともに、ベクトル/文字列などに物事を追加し続ける場合、アイテムをコピーする必要が少なくなることを意味します(メモリの作成は指数関数的であり、新しいアイテムの挿入はもちろん線形であるため)、したがって、このメモリ処理方法にかかる時間は、思ったほど長くはありません。償却分析の原則による、このメソッドを使用してベクトル/文字列/リストにアイテムを挿入するmのは、m 2ではなく、mのビッグシータのみであることがわかります。

于 2010-08-24T14:47:17.007 に答える