2016-08-18 5 views
5

イテレータが反復処理中の基底オブジェクトを保持しているかどうかについて多くの情報を見つけることはできません。C++イテレータは、基礎となるオブジェクトへの参照を保持していますか?

イテレータを作成すると、それを供給したオブジェクトが有効範囲外になります。イテレータが存在すると、イテレータが破棄されませんか?この例では

// This class takes a copy of iterators to use them later 
class Data { 
    public: 
    Data(std::vector<int>::iterator start, std::vector<int>::iterator end) 
     : start(start), 
     end(end) 
    {} 

    void show() { 
     // Use this->start and this->end for some purpose 
    } 

    private: 
    std::vector<int>::iterator start; 
    std::vector<int>::iterator end; 
}; 

Data test() { 
    std::vector<int> v{1, 2, 3}; 
    Data d(v.begin(), v.end()); 
    d.show(); // this would be ok 
    return d; 
} 

int main(void) { 
    Data d = test(); 
    d.show(); // What happens here? 
} 

Dataオブジェクトが最初show()コールの罰金ですイテレータのコピーが、保管されています

はここだけのシナリオを説明するために非常に簡単な例です。しかし、第2のshow()呼び出し時までに、イテレータを提供した元のオブジェクトは存在しなくなりました。

イテレータは、オブジェクト自体がすべて破壊されるまでオブジェクトを保持しますか、または元のオブジェクトが有効範囲外になるとすぐにイテレータを無効にしますか?ここで

は一つの方法または他の何が起こるか言っていないone reference of manyである(またはこれの結果は「未定義」されていてもか。)

+7

イテレータはポインタでモデル化されています。大まかに言えば、ポインタが高レベルのものXを実行できない場合、イテレータはどちらもできません。 –

+0

はい、イテレータは無効になり、結果は未定義です。 – songyuanyao

+1

特定の状況に対処するには、コンテナを破棄すると、すべてのイテレータが無効になります。 –

答えて

5

通常、イテレータは反復するデータを所有しません。実際には、データを所有しているオブジェクトのが認識されていることはまれです(これまであったとしても)。です。例えば、ベクトル・イテレータはポインタやポインタであり、ベクトルやその存続時間の知識はありません。ポインタ(ほとんどのもの)として実装されていないイテレータでも、一種の「ポインタ」と見なされ、そのように扱われることもあります。

あなたの例は、show()の無効なイテレータを2回目に逆参照するため、UBを使用しています。

コンテナが有効範囲外になると、すべてのイテレータが無効になります。実際には、there are all manner of reasons why an iterator may become invalidatedのように、その操作が容量拡張をもたらすときにベクトルに追加することなどがあります。

、それは「自分」データの種類、代わりに(例えばBoost's counting iteratorsなど)他の場所で見つかったいくつかのコレクションを反復処理を行うことをイテレータを見つけることは可能ですが、これらは魔法の機能を提供するために、C++を利用する魔法のプロパティですC++で定義されているイテレータの本質的なプロパティではありません。

2

イテレータは、その発信元限り一般のみ有効ですコンテナまたは「シーケンス」は変更されていません。変更によってメモリの再割り当てとメモリの移動が発生する可能性があるからです。イテレータ通常は参照メモリの元のコンテナ内にあるので、コンテナの変更によってイテレータが無効になる可能性があります。

これで、範囲外になるコンテナはデストラクタを実行します。それは明らかに変更コンテナであり、したがって、それに対するイテレータはプロセス中で無効になります。

1

最初に、イテレータには反復処理するオブジェクトを参照するインタフェースがありません。これはポインタの意味を実装するだけなので、抽象ポインタとして考えることができます。もちろん、それは内部実装がそのオブジェクトへのポインタを保持している可能性がありますが、実際の実装ではほとんど起こりません。

第2に、コンテナが破棄されたとき(そしてスコープから外れるとき)、コンテナ内のすべてのオブジェクトも破棄されます。したがって、コンテナが破棄された後はイテレータが無効になります。その後、イテレータをインクリメント、デクリメント、逆参照すると、未定義の動作が発生します。

関連する問題