2

次のコードがあります。

int main()
{
    vector<int> v;

    for(int i = 0; i < 10; ++i)
        v.push_back(i);

    auto it = v.begin() + 3;

    cout << "Iterator: " << *it << endl;

    vector<int>::reverse_iterator revIt(it);

    cout << "Reverse iterator: " << *revIt << endl;

}

このコードを実行すると、次の出力が得られます。

Iterator: 3
Reverse iterator: 2

2つの値が異なる理由を誰かが説明できますか?

4

4 に答える 4

6

逆イテレータは、有効な(およびそれぞれ)基本イテレータを使用して表現する必要がbaseあるため、1つの要素のオフセットを持つイテレータに「対応」します。たとえば、コンテナのイテレータの前を「指す」インターレータで表すことはできませんが、論理的にはそれを表します。したがって、's'ベースイテレータ'はです。したがって、の基本イテレータはになります。逆イテレータは、間接参照されるときに(または演算子を使用して)そのオフセットを自動的に調整します。rbegin()rend()end()begin()rend()begin()rend()begin()rbegin()end()*->

スコットマイヤーズによる古い記事は、素敵な写真と一緒に関係を詳細に説明しています:

ガイドライン3:reverse_iteratorのベースイテレータの使用方法を理解する

reverse_iteratorで基本メンバー関数を呼び出すと、「対応する」イテレータが生成されますが、それが何を意味するのかは明確ではありません。例として、このコードを見てください。このコードは、1〜5の数値をベクトルに入れ、reverse_iteratorを3を指すように設定し、イテレーターをreverse_iteratorのベースに設定します。

vector<int> v;

// put 1-5 in the vector
for (int i = 1; i <= 5; ++i) {
  v.push_back(i);
}

// make ri point to the 3
vector<int>::reverse_iterator ri =
  find(v.rbegin(), v.rend(), 3);

// make i the same as ri's base
vector<int>::iterator i(ri.base());

このコードを実行すると、次のようになります。

代替テキスト

この画像は素晴らしいです。begin()とend()に関してrbegin()とrend()のオフセットを模倣するreverse_iteratorとそれに対応するベースイテレータの特徴的なオフセットを表示していますが、必要なものがすべて揃っているわけではありません。知るために。特に、iを使用してriで実行したい操作を実行する方法については説明していません。

于 2012-04-29T16:44:31.743 に答える
4

ドキュメントには、最後の要素を処理するためにそれを行うと書かれているようです。つまり、最後の要素を超えたイテレータを逆にすると、新しい逆イテレータは最後の要素を指します。

于 2012-04-29T16:28:17.350 に答える
2

24.5.1リバースイテレータの最初の段落は次のように述べています。

クラステンプレートreverse_iteratorは、基になるイテレータによって定義されたシーケンスの最後からそのシーケンスの最初まで反復するイテレータアダプタです。逆イテレータとそれに対応するイテレータiの間の基本的な関係は、次のIDによって確立されます
&*(reverse_iterator(i)) == &*(i - 1)

によって返される値は、有効ではないため、のrend()前を指すことはできません。そのため、の値を含める必要があり、他のすべての逆イテレータをさらに1つシフトbegin()することが決定されました。これを補正し、とにかく正しい要素にアクセスします。rend()begin()operator*

于 2012-04-29T16:43:45.317 に答える
1

逆イテレータは、その範囲が 1 つシフトされるため、常に「1 つ前」、次に前方に見えます。

フォワード イテレータは begin() (最初の要素) から end() (最後の要素を過ぎて: [begin-end) は終了側で開かれます)

逆イテレータは定義によりrbegin() { return reverse_iterator(end()); }to にrend() { return reverse_iterator(begin()); }移動しますが、rbegin が最後 (「最後を過ぎた」ではない) であり、rend が「最初の前」(「最初」ではない) であるオープン範囲 [rbegin-rend] をウォークする必要もあります。 ) したがって、対応する 1 つの違い。

于 2012-04-29T16:52:07.000 に答える