在字符串中使用erase函数是否会使迭代器失效 [英] Does using the erase function in a string invalidate iterators

查看:231
本文介绍了在字符串中使用erase函数是否会使迭代器失效的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have the following code that takes a string and erases non alphabet characters

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

    }
}

我向我的教授展示了这个他告诉我,这样做有风险,因为它可能使我正在使用的迭代器无效。但是,我认为擦除只会在擦除点之后使迭代器无效,并且我确保在该点之后不使用任何迭代器。
那么这段代码会崩溃还是导致任何未定义的行为?

I showed this to my professor and he told me that doing this is risky because it may invalidate the iterator that I'm using. However, I thought that erase will only invalidate iterators after the point of the erase, and I made sure not to use any iterators after that point. So could this code crash or cause any undefined behavior?

推荐答案

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

std::vector::erase works as you suggest; it only invalidates iterators starting with the first erased element. However, that doesn't apply to std::string.

传统上,C ++标准对 std :: string 的要求更加灵活。 (或者,换句话说,它传统上允许实现者使用对向量无效的优化。)因此它与 std :: string :: erase 一致,和其他字符串变换器。

The C++ standard has traditionally been more flexible with the requirements for std::string. (Or, in other words, it has traditionally allowed implementers to use optimizations which would not be valid for vectors.) And so it is with std::string::erase, and other string mutators.

[string.require] (和n3797的第21.4.1节)中, standard接受:

In [string.require] (§21.4.1 of n3797), the standard accepts that:


  1. 引用 basic_string元素的引用,指针和迭代器序列可能会被 basic_string 对象的以下用法无效:

    • 作为参数引用非const basic_string 作为参数的任何标准库函数。

    • 调用非const成员函数,但 operator [] at 返回开始 rbegin 结束 rend

  1. References, pointers, and iterators referring to the elements of a basic_string sequence may be invalidated by the following uses of that basic_string object:
    • as an argument to any standard library function taking a reference to non-const basic_string as an argument.
    • Calling non-const member functions, except operator[], at, front, back, begin, rbegin, end, and rend.

换句话说,调用像<$ c $这样的潜在变异函数c> std :: string :: erase 可能使该字符串的所有迭代器无效,即使没有对字符串进行可见的修改(例如,因为范围是擦除是空的。)

In other words, calling a potentially mutating function like std::string::erase could invalidate all iterators to that string, even if no visible modifications are made to the string (for example, because the range to be erased is empty).

(最新的C ++标准草案具有相同的措辞,尽管它现在是第4段。)

(The latest draft C++ standard has the same wording, although it is now paragraph 4.)

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

In the first loop through the string, the iterator it has the value str.begin(). That iterator cannot be decremented, since the result would not be inside the string. And therefore, incrementing the decremented iterator might not return it to str.begin() for the next iteration.

以上都不适用于整数位置索引。因此,如果你可以安全地用非常相似的方式替换你的循环:

None of the above applies to integer position indices. So if you could safely replace your loop with the very similar:

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--);
    }
}

这篇关于在字符串中使用erase函数是否会使迭代器失效的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆