在C++ 11 array
,string
和vector
所有得到了data
方法,该方法:
返回指向用作元素存储的基础数组的指针.指针是范围[
data()
;data() + size()
)即使容器为空,也始终是有效范围.[ 来源 ]
此方法const
以所有适用容器的可变和版本提供,例如:
T* vector::data(); const T* vector ::data() const;
所有适用的容器,也就是除了string
其只提供const
版本:
const char* string::data() const;
这里发生了什么?为什么会被string
贬低,何时char* string::data()
会如此有用?
我认为这种限制来自于(2011年之前)的日子,它们std::basic_string
不必将其内部缓冲区存储为连续的字节数组.
而所有其他(std::vector
和其他)必须按照2003标准将其元素存储为连续序列; 所以data
很容易返回mutable T*
,因为迭代等没有问题.
如果std::basic_string
要返回一个mutable char*
,那就意味着你可以将它char*
视为一个有效的C字符串并执行C字符串操作strcpy
,如果字符串没有连续分配,那很容易转向未定义的行为.
C++ 11标准添加了basic_string
必须作为连续字节数组实现的规则.不用说,你可以通过使用旧技巧来解决这个问题&str[0]
.
简短的回答是c ++ 17确实提供了这种char* string::data()
方法.这对于类似的c ++ 17 data
函数至关重要,因此为了获得对底层C-String的可变访问,我现在可以这样做:
auto foo = "lorem ipsum"s; for(auto i = data(foo); *i != '\0'; ++i) ++(*i);
出于历史目的,值得记录string
的是c ++ 17正在构建的开发:在c ++ 11中,string
通过一个新的要求,它的元素被连续存储,以便对于任何给定的内容,可以访问底层缓冲区string s
:
&*(s.begin() + n) == &*s.begin() + n
对于n
[0
,s.size()
)中的任何一个,或者等效地,指针s[0]
可以传递给期望指向CharT[]
数组的第一个元素的指针的函数.
可以通过各种方法获得对这个新所需的底层C-String的可变访问,例如:&s.front()
,, &s[0]
或者&*s.first()
回到最初的问题,这将避免使用这些选项之一的负担:为什么没有访问string
的底层缓冲区是以char* string::data()
?的形式提供的?
要回答这一点,重要的是要注意T* array
并且T* vector
是c ++ 11所要求的添加.c ++ 11对其他连续容器没有额外的要求,例如deque
.当然,没有额外的要求string
,实际上string
连续的要求对于c ++ 11来说是新的.在此const char* string::data()
之前存在.虽然它是明确不保证被指向任何潜在的缓冲区,这是获得的唯一途径const char*
从string
:
返回的数组不需要以null结尾.
这意味着string
在c ++ 11转换到data
访问器时并没有"缩短" ,它只是没有被包括在内,因此只有先前拥有的const
data
访问者string
持久存在.在C++ 11的实现中有自然出现的例子,这需要直接写入a的底层缓冲区string
.