在c++11 array
,string
和vector
都获得了data
方法:
返回指向用作元素存储的基础数组的指针。指针是范围[
data()
;data() + size()
)始终是有效范围,即使容器为空。 [Source]
此方法以适用于所有适用容器的可变const
版本提供,例如:
T* vector<T>::data();
const T* vector<T>::data() const;
所有适用的容器,即string
除const char* string::data() const;
以外的string
char* string::data()
这里发生了什么?当static std::string tmp[] = { "a", "b", "c" };
static std::list<std::string> myList(tmp, tmp + 2);
如此有用时,为什么new Comparator<Bet>() {
public int compare(Bet b1, Bet b2) {
return b1.getPlayersHighScores().stream().mapToInt(Integer::valueOf).sum()
.compareTo(b2.getPlayersHighScores()stream().mapToInt(Integer::valueOf).sum());
}
}
会被忽略?
答案 0 :(得分:16)
我认为这种限制来自(2011年之前)的日子,std::basic_string
没有必要将其内部缓冲区存储为连续的字节数组。
虽然所有其他人(std::vector
等)必须按照2003标准将其元素存储为连续序列;所以data
可以很容易地返回mutable T*
,因为迭代等没有问题。
如果std::basic_string
要返回一个可变char*
,那就意味着您可以将char*
视为有效的C字符串并执行C strcpy
之类的C字符串操作如果字符串没有连续分配,那很容易转向未定义的行为。
C ++ 11标准添加了basic_string
必须作为连续字节数组实现的规则。不用说,你可以使用&str[0]
的旧技巧来解决这个问题。
答案 1 :(得分:14)
简短的回答是c++17确实提供了char* string::data()
method。这对于类似的c++17 data
function至关重要,因此为了获得对底层C-String的可变访问,我现在可以这样做:
auto foo = "lorem ipsum"s;
for(auto i = data(foo); *i != '\0'; ++i) ++(*i);
出于历史目的,值得记录c++17 string
正在开发的string
开发:c++11访问string s
&#39 ; s的底层缓冲区是可能的,因为它要求连续存储它的元素,以便任何给定的&*(s.begin() + n) == &*s.begin() + n
:
对于{n
,0
中的任何s.size()
,
s[0]
,或等效地,指向CharT[]
的指针可以传递给期望a的函数指向&s.front()
数组的第一个元素的指针。
可以通过各种方法获得对这个新所需的基础C-String的可变访问,例如:&s[0]
,&*s.first()
或string
但是回到原来的问题,这将避免使用以下选项之一的负担:为什么无法以char* string::data()
的形式提供对T* array<T>::data()
的基础缓冲区的访问权限?
要回答这一点,请务必注意T* vector<T>::data()
和deque
是c++11所要求的补充。 c++11对string
等其他连续容器没有额外要求。对const char*
来说,确实没有额外的要求,实际上要求string
was contiguous是c++11的新要求。在此const char* string::data()
存在之前。虽然它明确地 not 保证指向任何底层缓冲区,但它是从string
获取string
的唯一方法:
返回的数组不需要以null结尾。
这意味着data
没有&#34;被忽略&#34;在c++11过渡到const
个访问者的过程中,它只是没有被包含在内,因此只有data
string
先前拥有的string
monad
个访问者。有naturally occurring examples in C++11's implementation需要直接写入map :: (a->b) -> [a] -> [b]
的基础缓冲区。