39

std::stringC++11 では、が連続しており、ヌルで終了していることが保証されていることがわかっています (または、より厳密に言えばcharT()、 の場合charはヌル文字 0 で終了します)。

ポインターで文字列を埋めるために使用する必要があるこの C API があります。文字列全体 + null ターミネータを書き込みます。C++03 では、常に a を使用せざるを得ませんでした。これは、それが連続しているか、null で終了しvector<char>ていると想定できなかったためです。stringしかし、C++11 では (basic_string一部の標準ライブラリではまだ不安定なクラスが適切に準拠していると仮定して)、可能です。

それともできますか?私がこれを行うとき:

std::string str(length);

length+1文字列は、null ターミネータによって埋められた最後のバイトを割り当てます。それは良い。しかし、これを C API に渡すと、length+1文字が書き込まれます。null ターミネータを上書きします。

確かに、null-terminatorを null character で上書きします。これが機能する可能性は十分にあります (実際、どのように機能しないか想像できません)。

しかし、私は何が「機能する」かは気にしません。仕様に従って、null ターミネータを null 文字で上書きしてもよいかどうかを知りたいですか?

4

4 に答える 4

25

残念ながら、これは UB です。言葉遣いを正しく解釈すれば (いずれにせよ、許可されていません):

§21.4.5 [string.access] p2

戻り値: *(begin() + pos) if 、それ以外の場合は valuepos < size()の型のオブジェクトへの参照。参照値は変更してはなりませんTcharT()

T(そうではないという編集上の誤りcharT。)

.data()そして.c_str()基本的にoperator[]( §21.4.7.1 [string.accessors] p1) に戻ります:

戻り値: for each inのpようなポインター。p + i == &operator[](i)i[0,size()]

于 2012-10-05T06:44:31.370 に答える
11

仕様によると、終端を上書きすると未定義の動作NULになるはずです。したがって、正しいことは、文字列に文字を割り当て、文字列バッファを C API に渡し、次にに戻すことです。length+1resize()length

// "+ 1" to make room for the terminating NUL for the C API
std::string str(length + 1);

// Call the C API passing &str[0] to safely write to the string buffer
...

// Resize back to length
str.resize(length);

(FWIW、MSVC10で「NULの上書き」アプローチを試しましたが、正常に動作します。)

于 2012-10-05T08:36:16.727 に答える
10

LWG 2475は、次の仕様を編集することでこれを有効にしましたoperator[](size())(太字で挿入されたテキスト)。

charTそれ以外の場合は、 value の型のオブジェクトへの参照を返します。オブジェクトを 以外の値charT()に変更すると、 未定義の動作が発生します。charT()

于 2016-12-24T04:54:52.963 に答える
5

n3092はもう最新ではないと思いますが、それは私が持っているものです. セクション 21.4.5 では、単一の要素へのアクセスが許可されています。pos <= size() が必要です。pos < size() の場合は実際の要素を取得し、そうでない場合 (つまり pos == size() の場合) は変更不可能な参照を取得します。

プログラミング言語に関する限り、新しい値が古い値と同じであっても、値を変更できる種類のアクセスは変更と見なされると思います。

g++ には、リンクできるペダンティック ライブラリがありますか?

于 2012-10-05T06:33:16.643 に答える