index で「要素」にアクセスするときに明確に定義された動作が*d
あるかどうかという、質問が向けられているように見えるものとは何の関係もないため、無効である可能性を脇に置きましょう。std::string operator[]()
std::string::size()
C++03 標準には、string::operator[]()
(21.3.4 "basic_string
要素アクセス")の次の説明があります。
const_reference operator[](size_type pos) const;
reference operator[](size_type pos);
戻り値: の場合pos < size()
、 を返しますdata()[pos]
。それ以外の場合pos
== size()
、const バージョンは を返しますcharT()
。それ以外の場合、動作は未定義です。
s
コード例ではであるためconst
、動作は明確に定義されておりs[s.size()]
、null 文字が返されます。ただし、s
が でない場合const string
、動作は未定義です。
const
C++11は、このエッジ ケースで非 const バージョンとは非常に異なる動作をするバージョンのこの奇妙な動作を修正します。C++11 21.4.5「basic_string
要素アクセス」は次のように述べています。
const_reference operator[](size_type pos) const;
reference operator[](size_type pos);
必要: pos <= size()
.
戻り値: *(begin() + pos
) の場合pos < size()
、それ以外の場合は、値を持つ T 型のオブジェクトへの参照charT()
。参照値は変更されません。
string
したがって、C++11 コンパイラの場合、 が であるかどうかにかかわらず、動作は明確に定義されていconst
ます。
質問とは関係ありませんが、C++11 が「参照された値を変更してはならない」と言っているのは少し奇妙だと思いますpos == size()
。s[i] = some_character;
wheres
が非 const であることstd:string
やi < s.size()
. その未定義の動作は今ですか?その条項は特殊なケースのcharT()
オブジェクトにのみ適用されると思います。
もう 1 つの興味深い点は、どちらの標準も、 で返されるオブジェクトのアドレスが で返さs[s.size()]
れるオブジェクトのアドレスに関連していることを要求していないように見えることですs[s.size() - 1]
。つまり、返さcharT()
れる参照が文字列データの末尾に連続している必要はないようです。これは、必要に応じてそのセンチネル要素の単一の静的コピーへの参照を返すだけの選択肢を実装者に与えるためだと思います (これは、C++ 11 の「変更してはならない」という制限についても説明します。場合)。