Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/blackberry/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在字符串中使用擦除函数会使迭代器无效吗_C++_String_Iterator_Erase_Invalidation - Fatal编程技术网

C++ 在字符串中使用擦除函数会使迭代器无效吗

C++ 在字符串中使用擦除函数会使迭代器无效吗,c++,string,iterator,erase,invalidation,C++,String,Iterator,Erase,Invalidation,我有下面的代码,它接受一个字符串并删除非字母字符 void removeNonAlpha(string& str){ for (string::iterator it = str.begin(); it < str.end(); it++){ if (!(isUpperCaseLetter(*it) || isLowerCaseLetter(*it) || str == ' ')) str.erase(it--); }

我有下面的代码,它接受一个字符串并删除非字母字符

void removeNonAlpha(string& str){
    for (string::iterator it = str.begin(); it < str.end(); it++){
        if (!(isUpperCaseLetter(*it) || isLowerCaseLetter(*it) || str == ' '))  
            str.erase(it--);

    }
}
void removeNonAlpha(字符串和字符串){
对于(string::iterator it=str.begin();it
我向我的教授展示了这一点,他告诉我这样做是有风险的,因为这可能会使我使用的迭代器无效。然而,我认为擦除只会在擦除点之后使迭代器无效,并且我确保在该点之后不使用任何迭代器。
那么,这段代码会崩溃或导致任何未定义的行为吗?

std::vector::erase
按照您的建议工作;它只会使从第一个已擦除元素开始的迭代器无效。但是,这不适用于
std::string

C++允许字符串迭代器在帽子的作用下失效。 <> P>传统上,C++标准对<>代码STD::String < /代码>的要求更为灵活。(或者,换句话说,它传统上允许实现者使用对向量无效的优化。)而
std::string::erase
和其他字符串变体也是如此

[string.require]
(n3797的§21.4.1)中,本标准接受:

  • 引用
    basic_字符串
    序列元素的引用、指针和迭代器可能会因以下使用该
    basic_字符串
    对象而无效:
    • 作为任何标准库函数的参数,将对非常量
      basic\u字符串的引用作为参数
    • 调用非常量成员函数,除了
      操作符[]
      前面
      后面
      开始
      rbegin
      结束
      ,和
      趋势
  • 换句话说,调用一个可能发生变异的函数,如
    std::string::erase
    ,可能会使该字符串的所有迭代器无效,即使没有对该字符串进行可见的修改(例如,因为要擦除的范围为空)

    (最新的C++标准草案有相同的措辞,虽然现在是第4段)。 如果字符串的第一个字符不是字母,则建议的代码涉及未定义的行为。 在字符串的第一个循环中,迭代器

    it
    的值为
    str.begin()
    。该迭代器不能递减,因为结果不在字符串内。因此,递增递减迭代器可能不会在下一次迭代中将
    it
    返回到
    str.begin()

    使用索引而不是迭代器 以上所有内容均不适用于整数位置索引。因此,如果您可以安全地使用非常类似的

    void removeNonAlpha(string& str){
        for (auto sz = str.size(), i = 0; i < sz; ++i){
            if (!(isUpperCaseLetter(str[i]) ||
                  isLowerCaseLetter(str[i]) ||
                  str[i] == ' '))  
                str.erase(i--);
        }
    }
    
    void removeNonAlpha(字符串和字符串){
    对于(auto sz=str.size(),i=0;i
    您可以使用str.erase()的返回值,使用当前占用上一个迭代器所在位置的字符的迭代器更新迭代器。我假设这是一个有效的迭代器,不需要索引。itr=--str.erase(itr)@错误:原则上正确,但如果删除字符串中的唯一字符,则无效(因为在这种情况下不能减少结束迭代器)。另外,后减量的赋值是拙劣的imho。然后您可以执行itr=str.erase(itr);如果(itr!=str.end())--itr;(或从for循环中删除itr++并仅在else上递增)。