为什么在现代C ++中仍然限制std :: string :: data的const重载?

时间:2019-06-03 20:38:56

标签: c++ c++14

std::basic_string::dataits specification下有一个要求。

  

[string.accessors] (强调我的意思)

const charT* c_str() const noexcept;
const charT* data() const noexcept;
     

1 返回:指针p,使得p + i == &operator[](i)中每个i的{​​{1}}。

     

2 复杂度:恒定时间。

     

3 要求程序不得更改存储在字符数组中的任何值

在C ++ 03中,[0, size()]很有意义,因为它不必返回指向实际字符串缓冲区的指针,而对于c_str,则因为COW是可能的实现策略,因此它没有返回指针。即使缓冲区不是真正的常量,修改data也会干扰COW的不变性。

但是由于不允许使用C ++ 11 COW,因此datac_str返回相同的指针,并且它指向允许修改的缓冲区data。为什么然后通过operator[]修改指针仍然显式未定义行为?有实际原因吗?

1 个答案:

答案 0 :(得分:8)

  

我不是在谈论常量std::string,而是非常量

这就是为什么存在该语句的原因(甚至在C ++ 17中,当添加了非{const data时,它仍然存在)。因为data 不知道

在优化的小字符串string实现中,string对象本身存储字符数组。如果该string对象被声明为const,则其子对象也是如此。 Modifying objects declared as const is UB

相反,vector::data没有这样的语句,因为const vector总是 堆分配其数组。因此,虽然数组从外部逻辑上const,但从技术上讲它是定义良好的(但实际上,真的不应)从{ {1}} const_cast,因为您正在修改一个未创建为const的对象。

如果vector::data没有这样的声明,则基于SSO的实现将是不可能的,因为修改const的元素是合法,就像修改basic_string::data的元素是合法的。但是修改它不是合法的,因为它可能是一个const string对象,其数据存储在内部。