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

时间:2012-05-13 09:05:18

标签: c++ string c++11

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

void copy(std::string const& s, char *d) {
  for(int i = 0; i <= s.size(); i++, d++)
    *d = s[i];
}

他的应用程序崩溃,我认为这是因为这会使s超出范围,因为条件最多只能达到s.size() - 1

但是我旁边的其他人说过去有人讨论这是合法的。有人可以帮我解决这个问题吗?

3 个答案:

答案 0 :(得分: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);
     

返回:如果pos < size(),则返回data()[pos]。否则,如果pos == size(),则const版本返回charT()。否则,行为未定义。

由于示例代码中的sconst,因此行为定义良好,s[s.size()]将返回空字符。但是,如果s不是const string,则行为将是未定义的。

C ++ 11补救了const版本的奇数行为,与此边缘情况下的非const版本行为完全不同。 C ++ 11 21.4.5“basic_string元素访问”说:

const_reference operator[](size_type pos) const;
reference operator[](size_type pos);
     

需要:pos <= size()

     

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

因此,对于C ++ 11编译器,无论string是否为const,行为都是明确定义的。

与这个问题无关,我觉得有点奇怪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的“不应修改”限制,假设它仅适用于特殊情况)。

答案 1 :(得分:7)

cppreference says this:

reference       operator[]( size_type pos );

const_reference operator[]( size_type pos ) const;
     

如果pos==size()

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

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

答案 2 :(得分:0)

如果您想这样做(您的同事的代码也会尝试复制终止\0),您可以

  • 使用c_str()
  • 使用i < s.size()的循环,然后手动附加\0

编辑:
那么,从其他答案判断,我更倾向于认为Abyx的评论是正确的:数组d可能溢出(或者甚至可能没有分配)。先检查一下。
但请确保复制\0