7

最初に質問をし、次に動機を尋ねます。最後に、期待どおりにコンパイルおよび実行される例示的なコード サンプルを示します。

質問

イテレータを使用する必要がある期間中にイテレータが無効化されないことを確信できる場合、イテレータへのポインタ (たとえば、 a へのポインタlist<int>::iterator) を保持しても安全ですか。

動機

複数のコンテナーがあり、あるコンテナーに保持されているアイテムから別のコンテナーに保持されている対応するアイテムへの直接の相互参照が必要です。あるコンテナ内のアイテムが、別のコンテナ内に対応するアイテムを常に持っているとは限りません。

したがって、私の考えは、コンテナー #1 に格納されている要素内のコンテナー #2 内の要素へのイテレーターへのポインターを格納することです。なんで?イテレータを取得すると、コンテナ #2 の要素にアクセスできるだけでなく、必要に応じてコンテナ #2 の要素を消去することもできます。

コンテナー #2 に対応する要素があれば、コンテナー #1 の要素にイテレーターへのポインターを格納します。それ以外の場合、このポインターは NULL に設定されます。これで、イテレータへのポインタが NULL の場合、コンテナ #2 に対応する要素がないことをすばやく確認できます。NULL でない場合は、先に進んでそれにアクセスできます。

では、この方法でイテレータへのポインタを格納しても安全でしょうか?

コードサンプル

#include <iostream>
#include <list>

using namespace std;

typedef list<int> MyContainer;
typedef MyContainer::iterator MyIterator;
typdef MyIterator * PMyIterator;

void useIter(PMyIterator pIter)
{
    if (pIter == NULL)
    {
    cout << "NULL" << endl;
    }
    else
    {
    cout << "Value: " << *(*pIter) << endl;
    }
}

int main()
{
    MyContainer myList;

    myList.push_back(1);
    myList.push_back(2);

    PMyIterator pIter = NULL;

    // Verify for NULL
    useIter(pIter);

    // Get an iterator
    MyIterator it = myList.begin();

    // Get a pointer to the iterator
    pIter = & it;

    // Use the pointer
    useIter (pIter);
}
4

5 に答える 5

13

通常、反復子は値によって処理されます。たとえば、begin()andは(指定されたイテレータ型の)end()型のインスタンスを返しますが、毎回値のコピーを返すわけではありません。iteratoriterator&

もちろん、このコピーにアドレスを取得することはできますが、新しい呼び出しが同じアドレスを持つオブジェクトを返すことを期待することはできませんbegin()end()アドレスは、反復子オブジェクトを自分で保持している限り有効です。

std::vector<int> x { 1, 2, 3 };

// This is fine:
auto it = x.begin();
auto* pi = &it;

// This is not (dangling pointer):
auto* pi2 = &x.begin();

イテレータへのポインタを維持する意味はほとんどありません。イテレータはすでにデータへの軽量ハンドルです。それ以上の間接化は、通常、設計が不十分であることを示しています。特にあなたの例では、ポインターは意味がありません。通常のイテレータを渡すだけです。

于 2012-12-20T12:10:06.493 に答える
2

イテレータの問題は、コンテナにイテレータを無効にする多くの操作があることです (どれが問題のコンテナに依存するか)。イテレータを別のクラスに属するコンテナに保持すると、そのような操作がいつ発生するかわかりません。また、イテレータが現在無効であることを簡単に確認する方法はありません。

また、別のクラスに属するコンテナー内にある要素を直接削除することは、カプセル化の原則に違反します。別のクラスのデータを削除する場合は、そのクラスの public メソッドを呼び出してからデータを削除することをお勧めします。

于 2012-12-20T12:09:38.283 に答える
1

はい、他の型と同じようにイテレータへのポインタで作業することは可能ですが、あなたの例では元のイテレータを参照として渡すだけでよいので必要ありません。

一般に、コンテナを変更するとイテレータが無効になる可能性があるため、イテレータを格納することはお勧めできません。コンテナを保存し、必要に応じてイテレータを作成することをお勧めします。

于 2012-12-20T12:29:34.280 に答える
1

怖いですね。イテレータはオブジェクトです。スコープを離れると、ポインタは無効になります。コンテナ #2 のオブジェクトを消去すると、(コンテナによっては) すべてのイテレータが無効になり、ポインタが役に立たなくなります。

イテレータ自体を保存しないのはなぜですか? 何も参照しないコンテナー #1 の要素については、container2.end() を格納します。イテレータが無効化されていない限り、これは問題ありません。そうである場合は、マッピングを再生成する必要があります。

于 2012-12-20T12:15:53.530 に答える
1

はい、イテレータが無効化されず、スコープ外に出ないことを確認できる限り、安全です。

于 2012-12-20T12:09:49.910 に答える