我同事的代码看起来像这样:
void copy(std::string const& s, char *d) {
for(int i = 0; i <= s.size(); i++, d++)
*d = s[i];
}
Run Code Online (Sandbox Code Playgroud)
他的应用程序崩溃,我认为这是因为这种访问s超出了范围,因为条件应该只能达到s.size() - 1.
但是我旁边的其他人说过去有人讨论这是合法的.有人可以帮我清楚一下吗?
Mic*_*urr 10
让我们放弃*d无效的可能性,因为这与问题所针对的内容无关:std::string operator[]()在索引处访问"元素"时是否有明确定义的行为std::string::size().
C++ 03标准具有以下string::operator[]()(21.3.4" basic_string元素访问")的描述:
Run Code Online (Sandbox Code Playgroud)const_reference operator[](size_type pos) const; reference operator[](size_type pos);返回:If
pos < size(),返回data()[pos].否则,如果pos == size(),const版本返回charT().否则,行为未定义.
因为s在示例代码中const,行为定义良好s[s.size()]并将返回空字符.但是,如果s不是a const string,则行为将是未定义的.
const在这种边缘情况下,C++ 11补救了这种版本的奇数行为与非const版本的行为方式不同.C++ 11 21.4.5" basic_string元素访问"说:
Run Code Online (Sandbox Code Playgroud)const_reference operator[](size_type pos) const; reference operator[](size_type pos);要求:
pos <= size().返回:
*(begin() + pos)ifpos < size(),否则引用类型为T的对象的值charT(); 参考值不得修改.
因此,对于一个C++编译器11,行为是明确定义的是否string是const.
与这个问题无关,我发现C++ 11说"引用的值不应被修改"有点奇怪 - 我不清楚该条款是否仅适用于该条款pos == size().我敢肯定,有一吨的现有代码,做喜欢的东西的s[i] = some_character;地方s是一个非const std:string和i < s.size().这是不确定的行为吗?我怀疑该子句仅适用于特殊情况charT()对象.
另一个有趣的事情是,两个标准似乎都不要求返回的对象的地址s[s.size()]以任何方式与返回的对象的地址相关s[s.size() - 1].换句话说,似乎返回的charT()引用不必与字符串数据的末尾连续.我怀疑这是为了给实现者提供一个选择,如果需要,只返回对该Sentinel元素的单个静态副本的引用(这也解释了C++ 11的"不应修改"限制,假设它仅适用于特殊案件).
Run Code Online (Sandbox Code Playgroud)reference operator[]( size_type pos ); const_reference operator[]( size_type pos ) const;如果
pos==size(),
- const版本返回对值为CharT()(空字符)的字符的引用.(直到C++ 11)
- 两个版本都返回对值为CharT()(空字符)的字符的引用.通过非const引用修改空字符会导致未定义的行为.(自C++ 11以来)
只要你不修改空字符就可以了.