C ++標準ライブラリにstd::string
は、内部に割り当てられたストレージのサイズを返すパブリックメンバー関数capacity()
があります。これは、文字列の文字数以上の値です(ここによると)。この値は何に使用できますか?カスタムアロケータと関係がありますか?
7 に答える
容量を少なくとも指定された値に設定reserve()
するメンバー関数を使用する可能性が高くなります。
メンバー関数自体は、capacity()
メモリの割り当てを回避するために使用される場合があります。たとえば、使用済みの文字列をプールでリサイクルし、容量に基づいてそれぞれを異なるサイズのバケットに入れることができます。次に、プールのクライアントは、すでに最小容量を持つ文字列を要求できます。
この関数は、メモリを再割り当てする前に、に含まれる可能性string::capacity()
のある合計文字数を返します。これは、非常にコストのかかる操作です。std::string
Astd::vector
も同じように機能するので、割り当てられたメモリと初期化されたメモリの違いの詳細な説明については、std::vector
ここを参照することをお勧めします。
アップデート
うーん、質問を読み間違えたことがわかります。実際、std::stringまたはstd::vectorのいずれかで自分でcapacity()を使用したことはないと思いますが、とにかく予約を呼び出す必要があるため、ほとんど理由がないようです。
再割り当てすることなく文字列に含めることができる文字数を示します。これは、割り当てが高価で、それを避けたい状況では重要かもしれないと思いますが、これは実際のコードで使用したことのない文字列メンバー関数の 1 つだと言わざるを得ません。
文字列には容量とサイズがあります。容量は、より多くのメモリを割り当てる前に文字列が保持できる文字数を示します。サイズは、現在保持している文字数を示します。reserve()
文字列の最小容量を設定するために使用できます(少なくともその文字数にメモリを割り当てますが、それ以上割り当てることもできます)。
これは、文字列のサイズを大きくする場合に主に重要です。+=
またはを使用して文字列に連結するとappend()
、指定された文字列の文字が現在の文字列の最後に追加されます。文字列をそのサイズまで増やしても容量を超えない場合は、文字列が持っている容量を使用するだけです。ただし、新しいサイズが現在の容量を超える場合、文字列はメモリを内部で再割り当てし、その内部を新しいメモリにコピーする必要があります。これを頻繁に行う場合は、コストがかかる可能性があります(ただし、償却定数時間で実行されます)。そのため、このような場合は、reserve()
再割り当てが行われる頻度を減らすために十分なメモリを事前に割り当てるために使用できます。
ベクトル関数は、基本的に同じ関数で同じように機能します。
個人的には、ベクトルをときどき扱ってきましたがcapacity()
、reserve()
文字列を使ってそうする必要性はあまり見たことがありません。おそらく、コード内で文字列の連結を十分に行っていないためです。ほとんどの場合、特定の文字列はいくつかの連結を取得する可能性がありますが、その容量について心配するのに十分ではありません。容量について心配することは、通常、コードを最適化しようとするときに行うことです。
文字列に多くの文字を追加しようとしている場合は、パフォーマンスの調整に使用できます。文字列操作を開始する前に、容量を確認し、容量が小さすぎる場合は、1つのステップで目的の長さを予約できます(連続して大きなメモリチャンクを数回再割り当てするのではなく、パフォーマンスが低下します)。
関連する用途はほとんどありません。std :: vector::capacityに似ています。ただし、文字列の最も一般的な使用法の1つは割り当てです。std :: stringに割り当てると、その.capacityが変更される場合があります。これは、実装が古い容量を無視し、正確に十分なメモリを割り当てる権利を持っていることを意味します。
それは本当にあまり役に立たず、おそらく との対称性のためだけに存在しますvector
(両方が内部で同じように動作するという仮定の下で)。
ベクトルの容量は、サイズ変更の動作に影響を与えることが保証されています。ベクターのサイズを容量以下の値に変更しても、再割り当ては発生しないため、ベクター内の要素を参照する反復子またはポインターが無効になることはありません。これは、ベクトルで reserve を呼び出すことによっていくつかのストレージを事前に割り当ててから、(慎重に) サイズ変更またはプッシュバック (など) によって要素を追加できることを意味します。
ただし、そのような保証はありませんstring
。容量は情報提供のみを目的としているようです-とにかくそこから取得する有用な情報がないように見えるので、それはストレッチです. (さらに悪いことに、文字列文字の連続性も保証されていないため、文字列を線形バッファーとして取得できる唯一の方法はc_str()
、再割り当てを引き起こす可能性があることです。)
推測でstring
は、 はもともと のある種の特殊なケースとして実装されることを意図していたのですvector
が、時間が経つにつれて 2 つがバラバラになりました...