奇怪的迭代器行为

时间:2010-06-16 10:07:20

标签: c++ iterator

#include "stdafx.h"

int _tmain(int argc, _TCHAR* argv[])
{
    string s = "Haven't got an idea why.";
    auto beg =  s.begin();
    auto end = s.end();
    while (beg < end)
    {
        cout << *beg << '\n';
        if (*beg == 'a')
        {//whithout if construct it works perfectly
            beg = s.erase(beg);
        }
        ++beg;
    }
    return 0;
}

为什么我从此字符串中删除一个或多个字符,此代码会中断?我认为它与返回迭代器有关,因为擦除操作是在比end迭代器更高的地址创建的,但是我不确定它肯定是不正确的行为。或者是吗?

6 个答案:

答案 0 :(得分:8)

此代码存在一些问题。

  1. 不要缓存s.end()的值;它会在您删除元素时发生变化。
  2. 请勿使用beg < end。习惯的方法是写beg != end。如果您尝试迭代end,结果是未定义的,并且字符串库的调试版本可能会故意使您的进程崩溃,因此使用<毫无意义。
  3. s.erase(beg)返回的迭代器可能是s.end(),在这种情况下++beg会将您带到最后。
  4. 这是(我认为)正确的版本:

    int _tmain(int argc, _TCHAR* argv[])
    {
        string s = "Haven't got an idea why.";
        for (auto beg = s.begin(); beg != s.end();)
        {
            cout << *beg << '\n';
            if (*beg == 'a')
            {//whithout if construct it works perfectly
                beg = s.erase(beg);
            }
            else
            {
                ++beg;
            }
        }
    }
    

    编辑:我建议接受FredOverflow的回答。它比上述更简单,更快捷。

答案 1 :(得分:6)

从矢量或字符串逐个擦除元素具有二次复杂性。有更好的线性复杂解决方案:

#include <string>
#include <algorithm>

int main()
{
    std::string s = "Haven't got an idea why.";
    s.erase(std::remove(s.begin(), s.end(), 'a'), s.end());
    std::cout << s << std::endl;
}

答案 2 :(得分:4)

存储在end中的先前s.end()值在s.erase()之后无效。因此,不要使用它。

答案 3 :(得分:1)

注意basic_string的语义及它的迭代器。

来自www.ski.com/tech/stl

  

另请注意,根据C ++标准,basic_string具有非常不寻常的迭代器失效语义。迭代器可能通过交换,保留,插入和擦除(以及等效于插入和/或擦除的函数,例如清除,调整大小,追加和替换)而无效。但是,第一次调用任何非const成员函数(包括非const版本的begin()或operator [])可能会使迭代器无效。 (这些迭代器失效规则的目的是为实现者提供更大的实现技术自由。)

如果

,会发生什么
 beg = s.erase(beg);

返回等效于end()

的迭代器

答案 4 :(得分:1)

在调用擦除操作时,存储的结束迭代器指针变为无效。因此,在while循环条件中使用s.end()函数

答案 5 :(得分:0)

你必须从.end() - 1迭代到.begin()。同时,使用除==和!=。

之外的比较运算符是不安全的

这是我的代码:

    vector<long long> myVector (my, my+myCount);
    //sort and iterate through top correlation data counts
    sort (myVector.begin(), myVector.end());
    cout << endl;
    int TopCorrelationDataCount = 0;
    bool myVectorIterator_lastItem = false;
    vector<long long>::iterator myVectorIterator=myVector.end()-1;
    while (true) {                      
        long long storedData = *myVectorIterator;
        cout << TopCorrelationDataCount << " " << storedData << endl;                       

        //prepare for next item
        TopCorrelationDataCount++;
        //if (TopCorrelationDataCount >= this->TopCorrelationDataSize) break;
        if (myVectorIterator_lastItem) break;
        myVectorIterator--;
        if (myVectorIterator==myVector.begin())
        {
            myVectorIterator_lastItem = true;
        }
    }

注意:使用普通的for不能完成,因为你必须找出if ==。begin()。如果是,这将是您的最后一次迭代。你无法检查是否==。begin() - 1,因为它会导致运行时错误。

如果您只想使用向量中的X项,请使用TopCorrelationDataCount。