std::stringのお尻について
std::string
のオブジェクトをstr
とすると
-
*(str.date() + str.size())
は\0
。 -
*str.end()
は未定義動作。\0
が帰る保証が無い。 -
str[str.size()]
は\0
。書き換えなければ未定義動作にならない。
std::string
の有効範囲は、[basic.string.general]/3によると。
In all cases, [data(), data() + size()] is a valid range, data() + size() points at an object with value charT() (a “null terminator”), and size() <= capacity() is true.
-
std::string
は文字列終端保証がある。 - ポインタとして終端要素(
str.data() + str.size()
)にアクセスすると\0
が得られる。
std::string
のイテレータ範囲は文字列終端(\0
)を含まない。
そして、その終端イテレータのデリファレンス(*str.end()
)は未定義動作となる。
Returns an iterator to the character following the last character of the string. This character acts as a placeholder, attempting to access it results in undefined behavior.
basic_string
クラスのイテレータ範囲は、ヌル文字(\0
)終端ではない- この関数によって返されるイテレータは、
*this
が保持するいずれの要素も参照しない。その指す先は、不正な範囲となるだろう
規格の記述としては
Returns: An iterator which is the past-the-end value.
とだけあるが、イテレータ要件によってpast-the-end valueを指すイテレータが逆参照可能(dereferenceable)では無いことが示されており、これによって*str.end()
が未定義動作となる
Just as a regular pointer to an array guarantees that there is a pointer value pointing past the last element of the array, so for any iterator type there is an iterator value that points past the last element of a corresponding sequence. Such a value is called a past-the-end value. Values of an iterator i for which the expression *i is defined are called dereferenceable. The library never assumes that past-the-end values are dereferenceable.
添字アクセス([]
)はイテレータによって定義される([string.access]/2)
constexpr const_reference operator[](size_type pos) const;
constexpr reference operator[](size_type pos);
Preconditions: pos <= size().
Returns:*(begin() + pos)
ifpos < size()
. Otherwise, returns a reference to an object of typecharT
with valuecharT()
, where modifying the object to any value other thancharT()
leads to undefined behavior.
str[str.size()]
は、イテレータ範囲としては終端イテレータに到達しそれをデリファレンスしようとするため未定義動作になりそうだが、ここで特別扱いされて\0
が帰ることと書き換えなければ未定義動作にならないことが指定されている。
つまり?
- 文字列としての
std::string
はナル文字(\0
)を含んでいる - 範囲(
range
)としてstd::string
はナル文字を含まない - イテレータによる操作以外のところでは、
end
イテレータの位置にナル文字がある事を保証している -
std::string
のイテレータはポインタとは限らない