Some excerpts from the standard first:
Spec for string::operator[]()
:
const_reference operator[](size_type pos) const;
reference operator[](size_type pos);
Requires: pos <= size().
Returns: *(begin() + pos) if pos < size(), otherwise a reference to an object of type T with value charT(); the referenced value shall not be modified.
Complexity: constant time.
Spec for string::c_str()
and string::data()
:
const charT* c_str() const noexcept;
const charT* data() const noexcept;
Returns: A pointer p such thatp + i == &operator[](i)
for each i in [0,size()].
Complexity: constant time.
By combining these 2 specs, we can see that the pointer p
returned by c_str()
/data()
must satisfy that p[0...size()-1]
designates the elements of the string, and p[size()]
equals to operator[](size())
, which designates an object with the value charT()
. Since additive operator on a pointer is used to get the address of the string elements and the last charT()
object, they must be in a single array (you can't have just the string elements in place and create a charT()
object on-the-fly and return it). So is it safe to say that in C++11, str::string
is guaranteed to have the terminating null character in place in its underlying storage?
EDIT: My apology for failing to notice my question is a duplicate one. However, the answers I'm getting here seem to be conflicting with the answer in that duplicated question.
Also, I should have weakened my assumption like this: The underlying representation of std::string
should reserve enough space to hold the terminating null character, and take its freedom to set the charT()
value until c_str()
/data()
gets called. (i.e. The underlying storage must be able to hold at least size()+1
elements at any time.)