我同事的代码看起来像这样:
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以来)
只要你不修改空字符就可以了.