为什么 string::data() 不提供可变字符 *?
Why Doesn't string::data() Provide a Mutable char*?
在c++11中array
、string
、vector
都得到了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]
.
的老技巧来解决这个问题
简短的回答是 c++17 does provide the char* string::data()
method. Which is vital for the similarly c++17 data
function,因此为了获得对底层 C 字符串的可变访问权,我现在可以这样做:
auto foo = "lorem ipsum"s;
for(auto i = data(foo); *i != '[=10=]'; ++i) ++(*i);
出于历史目的,值得记录 string
的发展,其中 c++17 is building upon: In c++11 访问 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()
是 c++11. No additional requirements were incurred by c++11 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 c++11. Before this const char* string::data()
所要求的添加项。虽然它明确地 not 保证指向任何底层缓冲区,但它是从 string
:
获得 const char*
的唯一方法
The returned array is not required to be null-terminated.
这意味着 string
不是 c++11'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
.
的底层缓冲区
在c++11中array
、string
、vector
都得到了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]
.
简短的回答是 c++17 does provide the char* string::data()
method. Which is vital for the similarly c++17 data
function,因此为了获得对底层 C 字符串的可变访问权,我现在可以这样做:
auto foo = "lorem ipsum"s;
for(auto i = data(foo); *i != '[=10=]'; ++i) ++(*i);
出于历史目的,值得记录 string
的发展,其中 c++17 is building upon: In c++11 访问 string
的底层缓冲区是可能的,因为它的元素是连续存储的新要求这样对于任何给定的 string s
:
&*(s.begin() + n) == &*s.begin() + n
for anyn
in [0
,s.size()
), or, equivalently, a pointer tos[0]
can be passed to functions that expect a pointer to the first element of aCharT[]
array.
可以通过各种方法获得对这个新要求的底层 C 字符串的可变访问,例如:&s.front()
、&s[0]
或 &*s.first()
但是回到最初的问题避免使用以下选项之一的负担:为什么没有以 char* string::data()
的形式提供对 string
底层缓冲区的访问?
要回答这个问题,重要的是要注意 T* array<T>::data()
和 T* vector<T>::data()
是 c++11. No additional requirements were incurred by c++11 against other contiguous containers such as deque
. And there certainly wasn't an additional requirement for string
, in fact the requirement that const char* string::data()
所要求的添加项。虽然它明确地 not 保证指向任何底层缓冲区,但它是从 string
:
const char*
的唯一方法
The returned array is not required to be null-terminated.
这意味着 string
不是 c++11'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
.