为什么不#ctring :: data()提供一个Mutable char *?

时间:2015-12-08 12:01:45

标签: c++ string c++11 containers c-strings

arraystringvector都获得了data方法:

  

返回指向用作元素存储的基础数组的指针。指针是范围[data(); data() + size())始终是有效范围,即使容器为空。   [Source]

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

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

所有适用的容器,即stringconst 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()); } } 会被忽略?

2 个答案:

答案 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)

简短的回答是确实提供了char* string::data() method。这对于类似的 data function至关重要,因此为了获得对底层C-String的可变访问,我现在可以这样做:

auto foo = "lorem ipsum"s;

for(auto i = data(foo); *i != '\0'; ++i) ++(*i);

出于历史目的,值得记录 string正在开发的string开发:访问string s&#39 ; s的底层缓冲区是可能的,因为它要求连续存储它的元素,以便任何给定的&*(s.begin() + n) == &*s.begin() + n

  对于{n0中的任何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所要求的补充。 string等其他连续容器没有额外要求。对const char*来说,确实没有额外的要求,实际上要求string was contiguous的新要求。在此const char* string::data()存在之前。虽然它明确地 not 保证指向任何底层缓冲区,但它是从string获取string的唯一方法:

  

返回的数组不需要以null结尾。

这意味着data没有&#34;被忽略&#34;在过渡到const个访问者的过程中,它只是没有被包含在内,因此只有data string先前拥有的string monad个访问者。有naturally occurring examples in C++11's implementation需要直接写入map :: (a->b) -> [a] -> [b]的基础缓冲区。