为什么 string::data() 不提供可变字符 *?

Why Doesn't string::data() Provide a Mutable char*?

arraystringvector都得到了data方法,其中:

Returns pointer to the underlying array serving as element storage. The pointer is such that range [data(); data() + size()) is always a valid range, even if the container is empty. [Source]

此方法在所有适用容器的可变 const 版本中提供,例如:

T* vector<T>::data();
const T* vector<T>::data() const;

所有适用的容器,即 string 除外 only provides the const version:

const char* string::data() const;

这里发生了什么?为什么 string 会被亏空,而 char* string::data() 会如此有用?

我认为这个限制来自于(2011 年之前)std::basic_string 不必将其内部缓冲区存储为连续字节数组的日子。

而所有其他(std::vector 等)必须按照 2003 标准将其元素存储为连续序列;所以 data 可以很容易地 return 可变 T*,因为迭代等没有问题

如果 std::basic_string 是 return 可变的 char*,这意味着您可以将 char* 视为有效的 C 字符串并执行 C 字符串像 strcpy 这样的操作很容易变成未定义的行为,因为字符串不是连续分配的。

C++11 标准添加了 basic_string 必须作为连续字节数组实现的规则。不用说,您可以使用 &str[0].

的老技巧来解决这个问题

简短的回答是 does provide the char* string::data() method. Which is vital for the similarly data function,因此为了获得对底层 C 字符串的可变访问权,我现在可以这样做:

auto foo = "lorem ipsum"s;

for(auto i = data(foo); *i != '[=10=]'; ++i) ++(*i);

出于历史目的,值得记录 string 的发展,其中 is building upon: In 访问 string 的底层缓冲区是可能的,因为它的元素是连续存储的新要求这样对于任何给定的 string s:

&*(s.begin() + n) == &*s.begin() + n for any n in [0, s.size()), or, equivalently, a pointer to s[0] can be passed to functions that expect a pointer to the first element of a CharT[] array.

可以通过各种方法获得对这个新要求的底层 C 字符串的可变访问,例如:&s.front()&s[0]&*s.first() 但是回到最初的问题避免使用以下选项之一的负担:为什么没有以 char* string::data() 的形式提供对 string 底层缓冲区的访问?

要回答这个问题,重要的是要注意 T* array<T>::data()T* vector<T>::data(). No additional requirements were incurred by against other contiguous containers such as deque. And there certainly wasn't an additional requirement for string, in fact the requirement that was new to . Before this const char* string::data() 所要求的添加项。虽然它明确地 not 保证指向任何底层缓冲区,但它是从 string:

获得 const char* 的唯一方法

The returned array is not required to be null-terminated.

这意味着 string 不是 's transition to data accessors, it simply was not included thus only the const data accesor that string previously possessed persisted. There are naturally occurring examples in C++11's implementation 中的 "shortchanged",这需要直接写入 string.

的底层缓冲区