c++ - 配列 - "&s[0]"はstd:: stringの連続した文字を指していますか?




memcpy 配列 (4)

std :: stringの割り当ては、C ++ 98/03標準では連続しているとは限りませんが、C ++ 11ではそれが強制されます。 実際には、私もHerb Sutterも、連続ストレージを使用しない実装については知りません。

&s[0]は、長さ0の文字列の場合でも常にC ++ 11標準で動作することが保証されています。 str.begin()&*str.begin()実行した場合は保証されませんが、 &s[0]では標準でoperator[]ように定義されています:

戻り値pos < size() *(begin() + pos)場合は*(begin() + pos) 、そうでない場合は値charT()持つT型のオブジェクトへの参照。 参照される値は変更されないものとする

続いて、 data()は次のように定義されます。

戻り値: [0,size()]iについてp + i == &operator[](i)となるようなポインタp

(範囲の両端に角括弧があることに注意してください)

注意 :事前標準化C ++ 0xは、長さゼロの文字列(実際には明示的に未定義の動作でした)を扱うために&s[0]を保証しませんでした。 これは後の標準ドラフトで修正されているので、答えはそれに応じて更新されています。

私はいくつかのメンテナンス作業をしていて、次のようなものを走っていました:

std::string s;
s.resize( strLength );  
// strLength is a size_t with the length of a C string in it. 

memcpy( &s[0], str, strLength );

私は&s [0]がstd :: vectorの場合は安全だろうと知っていますが、これはstd :: stringの安全な使用ですか?


コードは機能するかもしれませんが、判断よりも運が多いと、実装が保証されていないことが前提となります。 私はコードの妥当性は無関係であると判断することを提案しますが、それは単純に以下のように簡単に減らすことができます。

std::string s( str ) ;

既存のstd :: stringオブジェクトに代入する場合は、次のようにします。

s = str ;

そして、std :: string自体がどのように結果を達成するかを決定させます。 あなたはこの種のナンセンスに頼るつもりならば、Cの文字列に関連するすべての危険を再導入しているので、std :: stringを使用しないでください。


内部文字列シーケンスがメモリに連続的に格納されているかどうかにかかわらず、これは一般的に安全ではありません。 連続性の他に、制御されたシーケンスがstd::stringオブジェクトによってどのように格納されるかに関する他の多くの実装の詳細があるかもしれません。

実際の実際の問題は次のようなものかもしれません。 std::stringの制御されたシーケンスは、ゼロ終端文字列として格納する必要はありません。 しかし、実際には、多くの(ほとんどの)実装では、内部バッファを1オーバーサイズにし、シーケンスをゼロ終了文字列として格納することを選択します。これは、 c_str()メソッドの実装を単純化するためです。あなたは終わった。

あなたの質問で引用したコードは、内部バッファにデータがコピーされてゼロ終了するような努力はしていません。 おそらく、 std::stringこの実装にゼロ終了が必要かどうかはわかりません。 おそらく、 resizeの呼び出し後に内部バッファにゼロが埋め込まれているため、実装によってゼロ終端文字に割り当てられる余分な文字は便利にゼロに事前設定されます。 すべてこれは実装の詳細です。つまり、この手法はかなり脆弱な仮定に依存しています。

言い換えれば、いくつかの実装では、 memcpyではなくstrcpyを使用して、そのような制御されたシーケンスにデータを強制する必要があるでしょう。 他の実装では、 strcpyではなくmemcpyを使用する必要があります。


技術的には、 std::stringはその内容をメモリに連続して格納する必要はないため、いいえ。

しかし、ほぼすべての実装(私が気づいているすべての実装)では、コンテンツは連続して格納され、これは「うまくいく」でしょう。





c++03