回答:
ドキュメントは正しいです。使用するc_str()
nullで終了する文字列が必要な場合にます。
実装者data()
がc_str()
あなたの観点から実装することになった場合、心配するdata()
必要はありません。文字列をnullで終了する必要がない場合でも使用します。実装によっては、c_str()よりもパフォーマンスが優れている場合があります。
文字列は必ずしも文字データで構成する必要はなく、任意のタイプの要素で構成できます。それらのケースでdata()
はより意味があります。c_str()
私の意見では、文字列の要素が文字ベースである場合にのみ本当に役立ちます。
Extra:C ++ 11以降では、両方の関数が同じである必要があります。つまりdata
、nullで終了する必要があります。cppreferenceによれば、「返される配列はnullで終了します。つまり、data()とc_str()は同じ機能を実行します。」
ではC ++ 11 / C ++ 0xの、data()
そしてc_str()
もはや異なっています。したがってdata()
、最後にもヌル終端が必要です。
21.4.7.1
basic_string
アクセサー[string.accessors]
const charT* c_str() const noexcept;
const charT* data() const noexcept;
1戻り値:
p + i == &operator[](i)
それぞれのi
inのようなポインタp[0,size()]
。
21.4.5 basic_string要素へのアクセス[string.access]
const_reference operator[](size_type pos) const noexcept;
1要件:pos <= size()。2戻り値:
*(begin() + pos) if pos < size()
、それ以外の場合、参照された値の値を持つタイプTのオブジェクトへcharT();
の参照は変更されません。
std::string
追加のメモリを割り当てる必要があります。あなたが行う場合は、両方と0に評価することが保証されているchar
'\0'
std::string s("\0");
s.data()[0]
s.data()[1]
それらが同じように動作すること、または.data()が.c_str()を呼び出すことを知っているとしても、これが他のコンパイラの場合に当てはまると想定することは正しくありません。コンパイラが将来のリリースで変更される可能性もあります。
std :: stringを使用する2つの理由:
std :: stringは、テキストと任意のバイナリデータの両方に使用できます。
//Example 1
//Plain text:
std::string s1;
s1 = "abc";
//Example 2
//Arbitrary binary data:
std::string s2;
s2.append("a\0b\0b\0", 6);
例1のように文字列を使用している場合は、.c_str()メソッドを使用する必要があります。
例2のように文字列を使用している場合は、.data()メソッドを使用する必要があります。これらの場合に.c_str()を使用するのは危険なためではなく、他の人が確認するためにバイナリデータを操作していることがより明確であるためです。あなたのコード。
.data()を使用した場合の潜在的な落とし穴
次のコードは誤りであり、プログラムでsegfaultを引き起こす可能性があります。
std::string s;
s = "abc";
char sz[512];
strcpy(sz, s.data());//This could crash depending on the implementation of .data()
実装者が.data()と.c_str()を同じようにすることはなぜ一般的ですか?
そうする方が効率的だからです。.data()にnullで終了しない何かを返す唯一の方法は、.c_str()または.data()に内部バッファーをコピーさせるか、2つのバッファーを使用することです。単一のnullで終了するバッファがあることは、std :: stringを実装するときに常に1つの内部バッファしか使用できないことを意味します。
それはすでに答えられています、目的に関するいくつかの注記:実装の自由。
std::string
操作(反復、連結、要素の変更など)では、ゼロターミネータは必要ありません。あなたが合格しない限りstring
ゼロで終了する文字列を期待する関数に、それは省略できます。
これにより、実装でサブストリングに実際のストリングデータを共有させることができます。 string::substr
できのコピー(および追加の割り当て)を回避して、共有文字列データへの参照と開始/終了範囲を内部的に保持できます。実装は、c_strを呼び出すか、文字列のいずれかを変更するまで、コピーを延期します。関係するストリンを読んだだけでは、コピーは作成されません。
(コピーオンライトの実装は、マルチスレッド環境ではそれほど面白くありません。さらに、一般的なメモリ/割り当ての節約は、今日のより複雑なコードの価値がないため、めったに行われません)。
同様に、string::data
ロープ(文字列セグメントのリンクされたリスト)などの異なる内部表現を許可します。これにより、挿入/置換操作が大幅に改善されます。この場合も、c_str
またはを呼び出すと、セグメントのリストを単一のセグメントに折りたたむ必要がありますdata
。
ANSI ISO IEC 14882 2003
(C ++ 03標準)からの引用:
21.3.6 basic_string string operations [lib.string.ops]
const charT* c_str() const;
Returns: A pointer to the initial element of an array of length size() + 1 whose first size() elements
equal the corresponding elements of the string controlled by *this and whose last element is a
null character specified by charT().
Requires: The program shall not alter any of the values stored in the array. Nor shall the program treat the
returned value as a valid pointer value after any subsequent call to a non-const member function of the
class basic_string that designates the same object as this.
const charT* data() const;
Returns: If size() is nonzero, the member returns a pointer to the initial element of an array whose first
size() elements equal the corresponding elements of the string controlled by *this. If size() is
zero, the member returns a non-null pointer that is copyable and can have zero added to it.
Requires: The program shall not alter any of the values stored in the character array. Nor shall the program
treat the returned value as a valid pointer value after any subsequent call to a non- const member
function of basic_string that designates the same object as this.
.data()
も存在するため、非定数文字列と同等ではなくなりました。