字符串[长度()]C++,可以吗
string[length()] in C++, is it OK?
我同事的代码看起来像这样:
void copy(std::string const& s, char *d) {
for(int i = 0; i <= s.size(); i++, d++)
*d = s[i];
}
他的应用程序崩溃了,我认为这是因为这超出了范围s
访问,因为条件应该最多 s.size() - 1
.
但是我旁边的其他人说,过去曾讨论过这是合法的。谁能为我澄清一下?
让我们抛开*d
无效的可能性,因为这与问题似乎针对的问题无关:在索引std::string::size()
访问"元素"时,std::string operator[]()
是否具有明确定义的行为。
C++03标准对string::operator[]()
(21.3.4"basic_string
元素访问"(有以下描述:
const_reference operator[](size_type pos) const; reference operator[](size_type pos);
返回:如果
pos < size()
,则返回data()[pos]
。否则,如果pos == size()
,则 const 版本返回charT()
。 否则,行为是未定义的。
由于示例代码中的s
是const
,因此行为是明确定义的,s[s.size()]
将返回一个空字符。 但是,如果s
不是const string
,则行为将是不确定的。
C++11 纠正了 const
版本的这种奇怪行为,在此边缘情况下,该行为的行为与非常量版本的行为大不相同。 C++11 21.4.5 "basic_string
元素访问"说:
const_reference operator[](size_type pos) const; reference operator[](size_type pos);
要求:
pos <= size()
。返回:
*(begin() + pos
( 如果pos < size()
,否则引用 到值为charT()
的 T 类型的对象;引用的值 不得修改。
因此,对于 C++11 编译器,无论string
是否const
,行为都是明确定义的。
与这个问题无关,我觉得 C++11 说"引用的值不得修改"有点奇怪——我不清楚该条款是否仅适用于pos == size()
的情况。 我很确定有大量现有的代码可以执行诸如s[i] = some_character;
之类的事情,其中s
是非常量std:string
和i < s.size()
。 现在这是未定义的行为吗?我怀疑该条款仅适用于特殊情况charT()
对象。
另一个有趣的事情是,这两个标准似乎都没有要求返回s[s.size()]
对象的地址与返回s[s.size() - 1]
对象的地址有任何关系。 换句话说,返回的charT()
引用似乎不必与字符串数据的末尾相邻。 我怀疑这是为了让实现者选择在需要时只返回对该哨兵元素的单个静态副本的引用(这也解释了 C++11 的"不得修改"限制,假设它仅适用于特殊情况(。
cppreference 是这样说的:
reference operator[]( size_type pos ); const_reference operator[]( size_type pos ) const;
如果
pos==size()
,
- const 版本返回对值为 CharT(((空字符(的字符的引用。(至C++11(
- 两个版本都返回对值为 CharT(((空字符(的字符的引用。通过非常量引用修改空字符会导致未定义的行为。(自C++11起(
所以只要你不修改空字符就可以了。
如果你想这样做(你的同事的代码也尝试复制终止