std::strings の capacity()、reserve()、resize() 関数 質問する

std::strings の capacity()、reserve()、resize() 関数 質問する

std::string を使用して動的バッファを作成し、インデックスを使用して反復処理するだけです。バッファを実際に割り当てる関数は resize() だけですか?

reserve() を試しましたが、インデックス経由で文字列にアクセスしようとするとアサートします。また、文字列のデフォルトの容量は 15 バイト (私の場合) のようですが、それでも としてアクセスできない場合はmy_string[1]

文字列の容量は実際のバッファではないのですか? また、reserve() も実際のバッファを割り当てないのですか?

string my_string;

// I want my string to have 20 bytes long buffer
my_string.reserve( 20 );

int i = 0;

for ( parsing_something_else_loop )
{
    char ch = <business_logic>;

    // store the character in 
    my_string[i++] = ch; // this crashes
}

reserve() の代わりに resize() を実行すると、正常に動作します。文字列に容量があるのに、[] で実際にアクセスできないのはなぜでしょうか? アクセスできるようにサイズを予約する目的はそこにあるのではないですか?

アドオン回答への返答として、stl の皆さんに質問したいのですが、resize() でまったく同じことができ、文字列も初期化できるのに、なぜ reserve() を使う人がいるのでしょうか。この場合、パフォーマンスの議論はあまりありがたくないと言わざるを得ません。reserve() に加えて resize() が行うことは、単にバッファを初期化することだけです。これは、いずれにしても行うのがよいことはわかっています。reserve() を島から追放することはできますか。

ベストアンサー1

アクセスできるようにサイズを予約する()ことがポイントではないでしょうか?

いいえ、それが のポイントですresize()

reserve()は、サイズの増加につながる将来の呼び出し ( の呼び出しなどpush_back()) がより効率的になるように、 に十分な余裕を与えるだけです。

あなたのユースケースからすると、代わりに を使用する必要があるようです.push_back()

my_string.reserve( 20 );

for ( parsing_something_else_loop )
{
    char ch = <business_logic>;
    my_string.push_back(ch);
}

文字列に容量があるのに、[] で実際にアクセスできないのはなぜでしょうか?

召命は.reserve()、山を爆破して無料の土地を与えるようなものです。無料の土地の量は です.capacity()。土地はありますが、そこに住むことができるわけではありません。入居するには家を建てなければなりません。家の数は.size()(= .length()) です。

都市を建設しているが、50番目の家を建設した後、土地が足りないことがわかったとします。そのため、51番目の家を建てるのに十分な大きさの別の場所を見つけ、そこに全人口を移住させる必要があります。これは非常に非効率的です。事前に1000軒の家を建てる必要があることがわかっていれば、次のように呼び出すことができます。

my_string.reserve(1000);

1000軒の家を建てるのに十分な土地を確保し、

my_string.push_back(ch);

この場所にを割り当てて家を建てますch。容量は1000ですが、サイズは1のままです。

my_string[16] = 'c';

16番の家はまだ存在しないので、

my_string.resize(20);

0番から19番までの住宅を一気に建てるため、

my_string[i++] = ch;

問題なく動作します(0 ≤≤ 19)。

参照http://en.wikipedia.org/wiki/ダイナミックアレイ


追加の質問については、

.resize()を完全に置き換えることはできません.reserve()。なぜなら、(1)割り当てられたスペースをすべて使い切る必要はなく、(2)デフォルトの構築+コピー割り当ては2段階のプロセスであり、直接構築するよりも時間がかかる可能性があるからです(特に大きなオブジェクトの場合)。

#include <vector>
#include <unistd.h>

struct SlowObject
{
    SlowObject() { sleep(1); }
    SlowObject(const SlowObject& other) { sleep(1); }
    SlowObject& operator=(const SlowObject& other) { sleep(1); return *this; }
};

int main()
{
    std::vector<SlowObject> my_vector;

    my_vector.resize(3);
    for (int i = 0; i < 3; ++ i)
        my_vector[i] = SlowObject();

    return 0;
}

走るのに少なくとも9秒は無駄になりますが、

int main()
{
    std::vector<SlowObject> my_vector;

    my_vector.reserve(3);
    for (int i = 0; i < 3; ++ i)
        my_vector.push_back(SlowObject());

    return 0;
}

たった6秒しか無駄になりません。

std::stringstd::vectorここでは のインターフェースのみをコピーします。

おすすめ記事