【C++】Runtime error:iterators incompatible 迭代器類型不一致

之前寫了下面這樣的一段代碼(數據類型簡化了一下,功能類似),結果老是報錯誤 "iterator can not dereference" 或者是 "iterators incompatible"的運行時錯誤.後來找到了問題的關鍵是一個疏忽,但是又容易犯,這裏記錄下方便以後遇到類似的問題給自己提個醒。
#include <iostream>
#include <list>
using namespace std;

class MyList
{
public:
    MyList(){}

    void addElement(int e)
    {
        m_list.push_back(e);
    }

    list<int> getList()
    {
        return m_list;
    }

private:
    list<int> m_list;
};

int main()
{
    MyList myList;
    myList.addElement(1);
    myList.addElement(2);
    myList.addElement(3);
    for (auto iter = myList.getList().cbegin();
         iter != myList.getList().cend(); ++iter)
    {
        cout << *iter << " ";
    }
    return 0;

不知道大家有沒有人一眼就看出了問題,反正我是折騰了老半天才找出問題,還是自己編碼疏忽不嚴謹導致的。

上面的問題關鍵在於,調用了兩次 getList()並獲取其相應的迭代器進行了比較。由於getList()返回的是MyList類內部的一個std::list<int> 的副本,所以兩次調用返回的 std::list<int>是內容相同的兩個副本,他們的迭代器指向不同的迭代區間,STL定義了不同容器的迭代器是不能比較的,所以導致上面錯誤。可以通過下面這行代碼來驗證:

 if (myList.getList().cbegin() != myList.getList().cend()){}

這段代碼僅僅只是比較一下兩個容器的迭代器,同樣引發程序運行時錯誤。

其實如果自己寫代碼時考慮周到一點就不會遇到這樣的低級錯誤了,下面是兩種改寫方法:
方法1:使用同一容器的迭代器比較
    list<int> m_list = myList.getList();
    for (auto iter = m_list.cbegin(); iter != m_list.cend(); ++iter)
    {
        cout << *iter << " ";
    }

方法 2 : 修改 MyList::getList() 方法,使其返回引用類型,這樣多次調用返回的都是同一容器

    list<int>& getList()
    {
        return m_list;
    }


發佈了50 篇原創文章 · 獲贊 27 · 訪問量 25萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章