Vector的新方法data()
提供了const和非const版本
但是,字符串data()
方法仅提供const版本。
我认为他们改变了关于std::string
的措辞,以便现在要求这些字符是连续的(如std::vector
)。
std::string::data
错过了吗?或者是一个很好的理由只允许const访问字符串的底层字符?
注意:std::vector::data
有另一个不错的功能,在空向量上调用data()
并不是未定义的行为。而&vec.front()
是未定义的行为,如果它是空的。
答案 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 P0272R1在charT* 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[]
语法糖,实用函数一样和一些封装。