代码之家  ›  专栏  ›  技术社区  ›  Evan Teran

这是非法的,对吗?

  •  11
  • Evan Teran  · 技术社区  · 14 年前

    对于一个个人项目,我一直在实现自己的libstdc++。一点一点地,我取得了一些很好的进展。通常,我会使用 http://www.cplusplus.com/reference/ 对于一些基本的测试用例,要确保我具有如预期那样工作的明显功能。

    今天我遇到了一个问题 std::basic_string::replace 特别是基于迭代器的版本,使用从站点逐字复制的示例( http://www.cplusplus.com/reference/string/string/replace/ ( 我添加了一条评论来指出问题所在。 ):

    // replacing in a string
    #include <iostream>
    #include <string>
    using namespace std;
    
    int main ()
    {
      string base="this is a test string.";
      string str2="n example";
      string str3="sample phrase";
      string str4="useful.";
    
      // function versions used in the same order as described above:
    
      // Using positions:                 0123456789*123456789*12345
      string str=base;                // "this is a test string."
      str.replace(9,5,str2);          // "this is an example string."
      str.replace(19,6,str3,7,6);     // "this is an example phrase."
      str.replace(8,10,"just all",6); // "this is just a phrase."
      str.replace(8,6,"a short");     // "this is a short phrase."
      str.replace(22,1,3,'!');        // "this is a short phrase!!!"
    
      // Using iterators:                      0123456789*123456789*
      string::iterator it = str.begin();   //  ^
      str.replace(it,str.end()-3,str3);    // "sample phrase!!!"
    
      // *** this next line and most that follow are illegal right? ***
    
      str.replace(it,it+6,"replace it",7); // "replace phrase!!!"
      it+=8;                               //          ^
      str.replace(it,it+6,"is cool");      // "replace is cool!!!"
      str.replace(it+4,str.end()-4,4,'o'); // "replace is cooool!!!"
      it+=3;                               //             ^
      str.replace(it,str.end(),str4.begin(),str4.end());
                                           // "replace is useful."
      cout << str << endl;
      return 0;
    }
    

    在我的replace版本中,是以临时字符串的形式实现的,我创建临时字符串,然后用它交换 *this . 这显然会使任何迭代器失效。那么我是否正确地认为这个例子是无效的?因为它存储迭代器,所以是否替换迭代器,然后再次使用迭代器?

    我的标准副本(ISO 14882:2003-21.3P5)上说:

    引用、指针和迭代器 指的是 基本的字符串序列可以是 失效的 通过使用这个基本的字符串对象:

    - As an argument to non-member functions swap() (21.3.7.8), 
      operator>>() (21.3.7.9), and getline() (21.3.7.9).
    - As an argument to basic_string::swap().
    - Calling data() and c_str() member functions.
    - Calling non-const member functions, except operator[](), at(),
      begin(), rbegin(),
      end(), and rend().
    - Subsequent to any of the above uses except the forms of insert() and
      erase() which return iterators,
      the first call to non-const member functions operator[](), at(), begin(),
      rbegin(), end(), or rend().
    

    关于非常量成员函数的条目似乎涵盖了这一点。所以除非我遗漏了一些东西,否则这段代码使用的是失效的迭代器,对吗?当然,这段代码与GCC的libstdc++很好地配合使用,但是我们都知道,在标准遵从性方面,这一点是无法证明的。

    1 回复  |  直到 14 年前
        1
  •  2
  •   Michael Kristofik    14 年前

    如果 replace 操作到位。不过,我认为不需要这样执行。所以是的,我会说你的代码在技术上是非法的。