为什么std :: vector :: data和std :: string :: data不同?

时间:2011-09-22 17:10:14

标签: c++ standards c++11

Vector的新方法data()提供了const和非const版本 但是,字符串data()方法仅提供const版本。

我认为他们改变了关于std::string的措辞,以便现在要求这些字符是连续的(如std::vector)。

std::string::data错过了吗?或者是一个很好的理由只允许const访问字符串的底层字符?

注意:std::vector::data有另一个不错的功能,在空向量上调用data()并不是未定义的行为。而&vec.front()是未定义的行为,如果它是空的。

4 个答案:

答案 0 :(得分:29)

在C ++ 98/03中,由于字符串经常被实现为COW这一事实,因此没有非const data()是有充分理由的。如果refcount大于1,非const data()将需要复制。尽管可能,这在C ++ 98/03中并不理想。

2005年10月,委员会在LWG 464投票,将const和非const data()添加到vector,并将const和非const at()添加到{ {1}}。那时,map没有改变,以便取消COW。但后来,通过C ++ 11,COW string不再符合。 {C} 11中的string规范也被收紧,因此它必须是连续的,并且string始终会显示终止空值。在C ++ 03中,终止空值仅由operator[](size())的常量重载保证。

简而言之,对于C ++ 11 operator[]来说,非const data()看起来更合理。据我所知,从未提出过。

<强>更新

string
2016年2月杰克逊维尔会议上C++1z working draft N4582 David Sankel's P0272R1charT* data() noexcept; 添加了basic_string

大卫好!

答案 1 :(得分:2)

历史上,字符串数据不是const,因为它会阻止几种常见的优化,例如写时复制(COW)。现在,IIANM很少见,因为它在多线程程序中表现不佳。

顺便说一句,是的,他们现在必须是连续的:

  

[string.require] .5:basic_string对象中类似char的对象应连续存储。也就是说,对于任何basic_string   对象s,身份&amp; *(s.begin()+ n)==&amp; * s.begin()+ n应保持n的所有值,使得0 <= n&lt; s.size()。

另一个原因可能是避免使用以下代码:

std::string ret;
strcpy(ret.data(), "whatthe...");

或任何其他返回预分配char数组的函数。

答案 2 :(得分:1)

虽然我不是很熟悉标准,但可能是因为std::string不需要包含以空值终止的数据,但它可以并且它不需要包含显式长度字段,但它可以。所以改变不正确的数据,例如在中间添加'\0'可能会使字符串长度字段与实际字符数据不同步,从而使对象处于无效状态。

答案 3 :(得分:0)

@Christian Rau

从最初的Plauger(我认为1995年左右)string类被委员会STL化(变成序列,模糊化)开始,std::string一直是std::vector加上与字符串相关的东西(转换自/到0终止,连接,......),加上一些奇怪的东西,比如COW实际上是“写入时复制而非const begin() / end() / operator[] ”。

但最终std::string实际上是另一个名称下的std::vector,其焦点和意图略有不同。所以:

  • 就像std::vector一样,std::string拥有大小数据成员或者包含起始和结束数据成员;
  • 就像std::vector一样,std::string并不关心其元素,嵌入式NUL或其他元素的价值。

std::string一个带有语法糖,实用函数和一些封装的C字符串,就像std::vector<T>不是T[]语法糖,实用函数一样和一些封装。