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

Why are std::vector::data and std::string::data different?

本文关键字:data std 不同 string vector 为什么      更新时间:2023-10-16

Vector的新方法data()提供了const和非const版本。
但是string的data()方法只提供const版本。

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

std::string::data刚好错过了吗?还是只允许const访问字符串的底层字符的好理由?

注意:std::vector::data还有一个很好的特性,在空向量上调用data()并不是未定义的行为。而&vec.front()如果为空则为未定义行为

在c++ 98/03中,有很好的理由不使用非const data(),因为字符串通常被实现为COW。如果refcount大于1,则非const data()需要进行复制。虽然这是可能的,但在c++ 98/03中并不被认为是理想的。

2005年10月,委员会在LWG 464中投票决定将const和非const data()添加到vector,将const和非const at()添加到map。当时,string还没有被修改为禁止COW。但是后来,在c++ 11中,COW string不再符合。string规范在c++ 11中也得到了加强,要求它是连续的,并且operator[](size())总是暴露一个终止null。在c++ 03中,终止null仅由operator[]的const重载保证。

所以简而言之,一个非const的data()看起来比一个c++ 11的string更合理。据我所知,这从来没有被提出过。

charT* data() noexcept;

在2016年2月的Jacksonville会议上由David Sankel的P0272R1将basic_string添加到c++ 1z工作草案N4582中。

干得好,David!

历史上,字符串数据不是const的,因为它会阻止一些常见的优化,比如写时复制(COW)。现在,ianm已经不那么常见了,因为它在多线程程序中表现得很糟糕。

BTW,是的,它们现在被要求是连续的:

[string.require]。5: basic_string对象中的类char对象应该连续存储。也就是说,对于任何basic_string对象s的恒等式&*(s.p begin() + n) == &* s.p begin() + n对所有n的值都成立,使得0 <= n std::string ret; strcpy(ret.data(), "whatthe...");

虽然我不是那么精通标准,但这可能是由于std::string不需要包含以空结束的数据,但它可以并且不需要包含显式的长度字段,但它可以。因此,更改底层数据,例如在中间添加''可能会使字符串长度字段与实际的char数据不同步,从而使对象处于无效状态。

@Christian Rau

从最初的Plauger(大约1995年我想)string类被委员会stl化(变成一个序列,模板化),std::string一直是std::vector加上字符串相关的东西(从/到0终止的转换,串联,…),再加上一些奇怪的东西,比如COW,实际上是"Copy on Write和non- const begin()/end()/operator[] "。

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

  • 就像std::vector一样,std::string要么有size数据成员,要么有开始和结束数据成员;
  • 就像std::vector一样,std::string不关心其元素的值,嵌入的NUL或其他。

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