2017-01-23 1 views
1

次のコードは、Microsoft Visual Studioの2015年には動作しません:このコードが期待どおりに機能しないのはなぜですか?

#include <vector> 
#include <list> 
#include <iostream> 

class ListWithIterator 
{ 
public: 
    ListWithIterator() : m_iterator(m_list.end()) {} 

    bool check() const { return m_iterator == m_list.end(); } 

private: 
    typedef std::list<int> list_t; 

    list_t m_list; 
    list_t::const_iterator m_iterator; 
}; 

int main(int, char**) 
{ 
    std::vector<ListWithIterator> v; 
    v.resize(1); 
    if (v[0].check()) 
    { 
     std::cerr << "Yes" << std::endl; 
    } 
    else 
    { 
     std::cerr << "No" << std::endl; 
    } 
    return 0; 
} 

MSVCは言う:

"デバッグアサートに失敗しました"、 "式:リストは、互換性のないイテレータ" check()関数内。

警告なしでそれをコンパイルしますが、それは間違っている作品++ G:

$ g++ sample.cpp -g -Og -Wall 
$ ./a.out 
No 
$ 

イテレータがm_list.end()しかしbool check() const { return m_iterator == m_list.end(); }戻りfalseによって初期化されたので、私は、 "はい" の出力を期待。

更新:

正解:

$ cat sample.cpp 
#include <vector> 
#include <list> 
#include <iostream> 

class ListWithIterator 
{ 
public: 
    ListWithIterator() : m_iterator(m_list.end()) {} 
    ListWithIterator(const ListWithIterator& from): m_list(from.m_list), m_iterator(m_list.end()) 
    { 
    } 

    bool check() const 
    { 
     std::cerr << m_list.size() << std::endl; 
     return m_iterator == m_list.end(); 
    } 

private: 
    typedef std::list<int> list_t; 

    list_t m_list; 
    list_t::iterator m_iterator; 
}; 

int main(int, char**) 
{ 
    std::vector<ListWithIterator> v; 
    v.resize(1); 
    if (v[0].check()) 
    { 
     std::cerr << "Yes" << std::endl; 
    } 
    else 
    { 
     std::cerr << "No" << std::endl; 
    } 
    return 0; 
} 
$ g++ sample.cpp -g -Og -Wall 
$ ./a.out 
0 
Yes 
$ 
+0

問題は、 'check_iterator'と' iterator'を 'check()'で比較していると思います。 – drescherjm

+0

はい、そうです。ペーストビンにログインする:http:// pastebin。com/FDziGfMm –

+0

いいえ、 'const_iterator'を' iterator'に変更しても動作しません。 –

答えて

4

あなたは-std=c++11フラグなしでコンパイル、一つだけpre-C++11 overloadがありますされています

void resize(size_type count, T value = T()); 

現在のサイズがカウント未満の場合、付加的な要素が追加され、値のコピーで初期化されています。


、不履行コピーコンストラクタ、コピー構造の両方の会員データとあなたが古いのイテレータで終わる未定義の動作につながる、後でcompare with an end iterator of a different list instanceリスト、(破壊)を。

C++ 11でコンパイルすると、動作が定義されます(デフォルトのコンストラクタを使用するオーバーロードが選択されます)。ただし、壊れたコピーのセマンティクスを修正するのはあなた自身の関心事です。

+0

Visual Studioに関しては、問題があったかどうかわかりません。 VS2015はその1パラメータの過負荷を持つ必要があります。それも働くように見えますか? – LogicStuff

+0

はい、そうです... –

3

あなたがListWithIteratorの暗黙のコピーコンストラクタをトリガしている場合は、あなたがリストのコピーコピーで終わりますイテレータの。ただし、コピーされたイテレーターは、オリジナルのリストを参照しています。異なるcontainsのイテレータの比較は未定義です。

ListWithIteratorのコピー先はわかりませんが、MSVCからのメッセージには、がコピーされていることが示唆されています。

3

コピーコンストラクタを定義しておらず、list::resizeはデフォルトで作成されたオブジェクトのコピーを挿入します。
このコピーには、コピー内のリストではなく、元のオブジェクトのリストを参照するイテレータが含まれています。

ポインタと同じようにイテレータに注意する必要があります。

関連する問題