2016-07-29 7 views
7

のstd ::ベクトルとは異なり、のstd :: stringはサイズを取る単項のコンストラクタを提供していません:std :: string(size、 ' 0')とs.resize(size)の違いは?

std::string s(size, '\0'); 

std::string s; 
s.resize(size); 

std::string s(size); // ERROR 

は何か違いがあります

を実装していますか?

文字列をすべてゼロに初期化するか、それとも指定されていない値にしますか?

ゼロの場合は、指定されたサイズの文字列を作成する方法はありますか?

+0

「サイズ」とは、「サイズ= 0」ですか? –

+1

@FirstStep:No、 'size'は'> 0'の 'size_t'です。 –

+0

パフォーマンスを測定するためにプロファイラを使用していくつかの実装を実行しましたか? –

答えて

4

std::string s(size, '\0');のように、文字列に必要なすべてのメモリを一度に割り当てることができます。しかしながら、第2の例では、sizeが小文字の最適化のために格納される文字の量より大きい場合、これは実装が定義されているにもかかわらず、余分な割り当てを実行しなければならない場合があり、その点では、準拠C++ 17実装。しかし、最初の例はより合理的であり、より効果的かもしれないので、おそらくそれが望ましいでしょう。 s.resize(size);を呼び出すと、すべての新しい文字はcharのデフォルトコンストラクタ、別名'\0'で初期化されます。指定されていない値でstringを初期化する方法はありません。

+4

2番目のケースで2番目の割り当てがあるのはなぜですか?どちらの場合でも、 'size'がSSOバッファより大きい場合、1つの割り当てがあります。 – Praetorian

+0

'make_unique()'が速いのと同じ理由で 'new'が呼び出され、コンストラクタが呼び出されます。最初のケースでは、すべてのメモリ 'std :: string'の必要を一緒に割り当てることができます。しかし、2番目のケースでは、 'new'を2回呼び出す必要があります。しかし、これは定義された実装ですが、私はそれを明確にします。 – DeepCoder

+6

* 'make_unique()'が速いのと同じ理由で、 'new'呼び出しとコンストラクタ*の呼び出しは、' make_unique'との違いがないので 'make_shared'を考えていますか?とにかく、 'std :: string'を構築するデフォルトを仮定しているのは、一度だけメモリを割り当てます。これは非常に珍しいことですが、許可されています。しかし、まだ違いがあると主張するのは間違っているようです。いくつかの変数を '0'に初期化してから、それらを変更すること、それらを初期化することを' size'で開始すること、差異を考慮しない限り、違いがあるかもしれませんが、ほとんどそうではありません。 – Praetorian

4

実際の回答は実装ベースですが、私はかなりstd::string s(size, '\0');がより高速であると確信しています。

std::string s; 
s.resize(size); 

documentation for std::stringによると、

1)デフォルトコンストラクタ。空の文字列を作成します(サイズはゼロで、容量は指定されていません)。

デフォルトのコンストラクタは、「容量不定」の文字列を作成します。私のここでの感覚は、実装がおそらく10-15文字の領域(完全に推測)のデフォルト容量を自由に決定できることです。 sizeが現在capacityより大きい場合

は、その後、次の行では、新しいsizeとメモリ(resize)を再割り当てします。これはおそらくあなたが望むものではありません!

本当に確実に見つけたい場合は、2つの方法でプロファイラを実行できます。

2

DeepCoderから既に良い答えがあります。

  • size():それは(すなわち意味の)実際の文字の数の記録のために

    しかし、私は(ベクトル用など)の文字列が、2つの異なる概念であることを指摘したいと思います文字列。resize()(これには、'\0'以外である必要がある場合は、フィラーとして使用する文字を示す2番目のパラメータを指定できます)

  • capacity():文字列に割り当てられた文字数です。その大きさは少なくともそれ以上であることがあります。あなたはそれを増やすことができますreserve()

あなたが割り当てのパフォーマンスを心配している場合、私はそれが能力を持つ方が良いと信じています。文字列内の実際の文字のためにサイズを保持する必要があります。

ところで、より一般的には、s.resize(n)s.resize(n, char())と同じです。したがって、工事のときと同じ方法で記入したい場合は、string s(n, char())と考えることができます。しかし、Tと文字が異なるためにbasic_string<T>を使用しない限り、あなたの '\ 0'はそのトリックを行います。

1

Resizeは要素を初期化しないままにしません。ドキュメントによると、​​

s.resize(size)は、付加された各文字を値で初期化します。これにより、サイズ変更された文字列の各要素は'\0'に初期化されます。

価値のある違いがあるかどうかを実際に判断するには、特定のC++実装のパフォーマンスの違いを測定する必要があります。

Visual C++で生成されたマシンを最適化されたビルドで見た後、どちらのバージョンのコードの量も同じであることがわかります。直感的ではないと思われるのは、resize()のバージョンがであることがわかります。です。それでも、独自のコンパイラと標準ライブラリをチェックする必要があります。

関連する問題