std ::文字列でない「&S [0]」の連続した文字をポイント?
質問
私は次のようなものを越え、いくつかの保守作業とRANをやってます:
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 );
私が使用して知っている&それがのstd ::ベクトルだったが、これはのstd ::文字列を安全に使用するのですか?あればS [0]が安全だろう。
解決
Aのstd ::文字列の割り当ては、それがためにC ++ 98/03標準の下で連続している保証はなく、C ++ 11の力されていません。実際には、どちらも私も連続したストレージを使用しない実装のハーブサッターを知っています。
&s[0]
の事があっても、常に長さ0の文字列の場合には、C ++ 11標準で動作することが保証されていることに注意してください。あなたがstr.begin()
や&*str.begin()
をしたかどうかは保証されませんが、&s[0]
のための標準的な定義はようoperator[]
ます:
戻り:
*(begin() + pos)
pos < size()
場合、値T
有するタイプcharT()
のオブジェクトへさもなければ参照。参照値が変更されてはならない
に引き続き、data()
は次のように定義され
の戻り値:のAポインタ
p
p + i == &operator[](i)
の各i
ため、このようなこと[0,size()]
(通知範囲の両端の角括弧)
<時間> のお知らせの:あらかじめ標準C ++ 0xのが保証長さゼロの文字列(実際には、それが明示的に未定義の動作でした)との仕事に&s[0]
、およびこの回答の古いリビジョンは、このことを説明しませんでした。答えはそれに応じて更新されているので、これは、後の標準草案に修正されています。
他のヒント
技術的には、無、std::string
ので、メモリ内に連続し、その内容を保存する必要がない。
しかし、ほとんどすべての実装(私は承知していたのすべての実装)で、内容が連続して格納されており、これだろう「作品。」
これは、使用しても安全です。私はほとんどの答えはかつて正しかったと思いますが、標準が変更されました。 Cから引用++ 11標準、の一般的な要件をのbasic_string [string.require] の、21.4.1.5、言います:
はチャー状のbasic_stringオブジェクト内のオブジェクトが連続して格納されなければなりません。それはどんなのbasic_stringのために、あります オブジェクトS、アイデンティティ&*(s.begin()+ N)==&* s.begin()+ N Nそのような0そのすべての値に対して保持しなければなりません <= N
その前に少し、それはすべてのイテレータがランダムアクセス反復子であることを述べています。両方のビットは、あなたの質問の使用をサポートしています。 (また、Stroustrup氏は明らかに彼の最新の本の中でそれを使用しています;))
これは、この変更はC ++ 11で行われた可能性は低いではありません。私は、同じ保証はまた、そのリリースに非常に便利なのデータ()のポインタを得たベクトル、のために、その後追加されたことを覚えているようだ。
希望に役立ちます。
読者は、この質問は、C ++ 03標準は、現在の出版だった2009年、に頼まれたことに注意してください。この回答はstd::string
sは、のの連続したストレージを利用するために保証されていない標準、そのバージョンに基づいています。この質問は、特定のプラットフォーム(gccのような)のコンテキストで頼まれていなかったので、私はOPのプラットフォームに関する仮定をしない - 、天候やない特にそれがstring
ためcontigiousストレージを利用
法律?多分そうでないかもしれません。安全?おそらく、しかし、そうでないかもしれません。良いコード?さて、行こうではないが...
だけでないのはなぜます:
std::string s = str;
...またはます:
std::string s(str);
...またはます:
std::string s;
std::copy( &str[0], &str[strLen], std::back_inserter(s));
...またはます:
std::string s;
s.assign( str, strLen );
コードはうまくいくかもしれないが、より多くの判断より運で、それは保証されません実装についての仮定を行います。私はそれが簡単だけに縮小されて合併症を超える無意味である一方で、コードの有効性を判断することは無関係であることを示唆ます:
std::string s( str ) ;
または既存のstd ::文字列オブジェクトに割り当てる場合は、ちょうどます:
s = str ;
その後、とstd ::文字列自体が結果を達成するための方法を決定しましょう。あなたはナンセンスのこの種に頼るしようとしている場合は、同様にあなたがC文字列に関連付けられているすべての危険性を再導入しているためにはstd :: stringとスティックを使用できない場合があります。
これはのないの安全に関係なく、内部文字列の順序が連続したりしないメモリに記憶されているかどうかの一般的です。制御シーケンスは継続のほか、std::string
オブジェクトによって格納される方法に関連する他の多くの実装の詳細であるかもしれないがあります。
それと本当の実用上の問題は、以下のかもしれません。 std::string
の制御配列はゼロで終了する文字列として格納する必要はありません。ただ、内部バッファへのポインタを返し、あなたは、次のとおりです。それはc_str()
メソッドの実装を簡素化するためしかし、実際には、多くの(?ほとんど)の実装は1で内部バッファを大型化し、とにかくゼロで終了する文字列としてシーケンスを格納するように選択しました行わ。
あなたがあなたの質問に引用されたコードは、ゼロ終了データを内部バッファにコピーされるまでどんな努力をしていません。恐らくそれは単にゼロ終端がstd::string
のこの実装のために必要であるかどうか分かりません。実装によってゼロターミネータ用に割り当てられた余分な文字は、便利ゼロに予め設定されているので、恐らくそれは、resize
への呼び出しの後にゼロで満たされている内部バッファに依存しています。このすべては、この技術は、いくつかのかなり脆弱な仮定に依存していることを意味し、実装の詳細です。
言い換えれば、いくつかの実装では、おそらくそのような制御配列へデータを強制的にstrcpy
ない、使用memcpy
する必要があると思います。いくつかの他の実装では、あなたがmemcpy
なくstrcpy
を使用する必要があると思いますが。