C++中的字符串[length()],可以吗?

Joh*_*itb 8 c++ string c++11

我同事的代码看起来像这样:

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元素访问")的描述:

const_reference operator[](size_type pos) const;
reference operator[](size_type pos);
Run Code Online (Sandbox Code Playgroud)

返回: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元素访问"说:

const_reference operator[](size_type pos) const;
reference operator[](size_type pos);
Run Code Online (Sandbox Code Playgroud)

要求:pos <= size().

返回:*(begin() + pos)if pos < size(),否则引用类型为T的对象的值charT(); 参考值不得修改.

因此,对于一个C++编译器11,行为是明确定义的是否stringconst.

与这个问题无关,我发现C++ 11说"引用的值不应被修改"有点奇怪 - 我不清楚该条款是否仅适用于该条款pos == size().我敢肯定,有一吨的现有代码,做喜欢的东西的s[i] = some_character;地方s是一个非const std:stringi < s.size().这是不确定的行为吗?我怀疑该子句仅适用于特殊情况charT()对象.

另一个有趣的事情是,两个标准似乎都不要求返回的对象的地址s[s.size()]以任何方式与返回的对象的地址相关s[s.size() - 1].换句话说,似乎返回的charT()引用不必与字符串数据的末尾连续.我怀疑这是为了给实现者提供一个选择,如果需要,只返回对该Sentinel元素的单个静态副本的引用(这也解释了C++ 11的"不应修改"限制,假设它仅适用于特殊案件).


Pub*_*bby 7

cppreference说:

reference       operator[]( size_type pos );

const_reference operator[]( size_type pos ) const;
Run Code Online (Sandbox Code Playgroud)

如果pos==size(),

  • const版本返回对值为CharT()(空字符)的字符的引用.(直到C++ 11)
  • 两个版本都返回对值为CharT()(空字符)的字符的引用.通过非const引用修改空字符会导致未定义的行为.(自C++ 11以来)

只要你不修改空字符就可以了.

  • 要明确一点 - 如果使用前C++ 11编译器,如果`s`不是`const`则对s [s.size()]`的访问是未定义的 - 在问题代码中访问是正常的只是因为`s`是`const`(对于前C++ 11编译器).它与null字符是否被修改无关,只是`s`是否为`const`.当然,这些都没有说明"*d"可能无效的可能性. (4认同)