0

Iterの実装に基づいて、私は理解するのが難しく、operator!=なぜそれがチェックされないのか理解できませんか_p_vec

operator!=これは、を比較するだけの推奨実装です_pos

class Iter
{
    public:
    Iter (const IntVector* p_vec, int pos)
        : _pos( pos )
        , _p_vec( p_vec )
    { }

    // these three methods form the basis of an iterator for use with
    // a range-based for loop
    bool operator!= (const Iter& other) const
    {
        return _pos != other._pos;
    }
    ...
    ...
    private:
        int _pos;
        const IntVector *_p_vec;
};

しかし、これを行う正しい方法は次のように思います。つまり、との両方を比較する必要が_posあり_p_vecます。

bool Iter::operator!= (const Iter& other) const
{
    return _p_vec != other._p_vec || _pos != other._pos;
}

質問>誰のコードが正しいですか?

===イテレータの比較でstd::vectorがどのように機能するかを更新====

std::vector<int> vecOne { 1, 2, 3};
std::vector<int> vecTwo { 4, 5, 6};

auto iterOne = vecOne.begin();
std::advance(iterOne, 1);

auto iterTwo = vecTwo.begin();
std::advance(iterTwo, 1);

if ( iterOne == iterTwo)
    std::cout << "iterOne == iterTwo" << std::endl;
else
    std::cout << "iterOne != iterTwo" << std::endl;

出力は:iterOne != iterTwo

でも、

std::vector<int> foo;
std::vector<int> bar;

if ( foo.begin() == bar.begin() )
    std::cout << "foo.begin() == bar.begin()" << std::endl;
else
    std::cout << "foo.begin() != bar.begin()" << std::endl;

出力は:foo.begin() == bar.begin()

GCC(バージョン4.7.1)

4

2 に答える 2

2

また、基になるコンテナ参照を比較することは、たとえば、begin()2つの異なるコンテナのイテレータが等しく比較されることを確認するための改善です。

ただし、異なるコンテナーのイテレーターが比較されることはめったにありません(STLアルゴリズムを使用する場合、イテレーターは比較されません)。したがって、これは最適化と見なされる可能性があります。begin()からにステップするループを考えてみてください。したがって、比較しているイテレータは、同じコンテナend()の「現在の」イテレータとです。end()

標準コンテナ(ベクトルなど)のイテレータを比較すると、未定義の動作と見なされます。実際、それらは(適切な)コード(たとえば標準アルゴリズム)で比較されることはないため、そのような場合の動作を定義する必要はありません。

したがって、このIterクラスの作成者は、この点に戻って、「異なるベクトルのイテレータを比較することは未定義の動作です」と言いたい場合もあります。

そうは言っても、異なるコンテナーのイテレーターを決して比較しないようにしたい場合は、このチェックを省略し、デバッグビルド用にアサートする可能性があります(ただし、リリースビルドではチェックしないでください)。

異なるコンテナのイテレータを比較したい場合の良い例は、リンクリストの場合です。ここでは、リストの最後をnullポインタ(または静的nullアイテムインスタンスへのポインタ)として定義します。イテレータがリンクリストアイテムへのポインタであると考えてください。この場合、end()イテレータは単なるnullポインタです(またはこのnullアイテムを指します)。これはすべてのコンテナで同じであるため、このような場合、比較メソッドでチェックを実装することはできません。おそらくこれが、そのような比較が定義されていない理由の1つです。異なるリストのエンドイテレータを比較するときに「等しくない」を返す必要がありますが、それはできません

于 2013-02-01T16:04:16.967 に答える
2

原則として、イテレーターのユーザーは、異なるコンテナーのイテレーターを比較することは想定されていません。標準ライブラリでは、そうすることは未定義の動作です。

したがって、標準ライブラリと同じくらい堅牢なイテレータを作成しようとしているだけであれば、コンテナを比較する必要はありません。ただし、コンテナへのポインタが周りにある場合は、少なくともデバッグでコンテナが一致することを確認してから、この比較を行うべきではないと断言するのが礼儀です。

リリースでも自由にチェックできますが、コードを使用するイテレータが標準のコンテナでも機能することになっている場合は、異なるコンテナのイテレータに依存して等しくないことを比較することはお勧めしません。

未定義動作について話している人については、さまざまなコンテナーのイテレーターを比較するを参照してください。

于 2013-02-01T16:09:58.843 に答える