2010-12-05 15 views
10

がハーフオープン範囲のSTLの概念をサポートするために、我々は、アレイの1-過去エンドを指すように許可されています。 3つの要素からなるベクトルがあるとします。 std::vector::iterator場合、これらの場所にbeginendと点通常のリリースの場合のように構築し、ポインタとして実装されている:ドットが一過去エンド擬似要素を表すどこにポイントがありますか?

+---+---+---+.... 
    | | | | . 
    +---+---+---+.... 
    ^  ^
    begin  end 

。 1つ前のようなものはないので、正確にはrendを指していますか?私が説明しましょう:rendは違法ポインタであるため、

+---+---+---+.... 
    | | | | . 
    +---+---+---+.... 
^  ^
rend  rbegin 

は明らかに、図は、間違っています。だから私はstd::vector::reverse_iteratorの実装は、リリースビルドでさえ、ポインタになることはないと思います。

私は正しいですか? reverse_iteratorを実装する最も効率的な方法は何でしょうか?

答えて

3

reverse_iteratorが論理的にそれに含まれるイテレータのポイントに、何を指しているものを何の違いがあります。論理的には、rbeginは、シーケンスの最後の要素を指すとrendを開始する前に一つの要素を指すイテレータを生成するイテレータを生成します。しかし、これは、通常、逆イテレータが指し示している要素を通過する1つの要素を指す基本イテレータで実装されます。このような何か:

template<class Iter> 
class reverse_iter 
{ 
    Iter base; 
public: 
    explicit reverse_iter(Iter it) : base(it) {} 

    reference operator*() const { 
     Iter tmp = base; 
     --tmp; 
     return *tmp; 
    } 

    reverse_iter& operator++() {--base; return *this;} 
}; 

だから、あなたは終わり、過去1にcontainer.end()で、ベースイテレータのポイントを、このようなreverse_iter<>オブジェクトを初期化するが、逆イテレータを逆参照することはあなたの最後の要素を与える場合。大丈夫です。

5

あなたは、容器の外に指すイテレータを逆参照を許可していないので、それはない、実際にどのようなrend()「ポイント」にありません。それは、コンテナ/イテレータ型に特定の意味を持っている任意の値にすることができ、法的ポインタ値である必要はありません。

+1

Cでは、ポインタがオブジェクトまたはオブジェクトの最後の要素を指していない場合、そのポインタが評価される(参照解除されない)場合、その動作は未定義です。この質問はC++に関するものですが、そこには違いはないと私は考えています。私はあなたが何を意味するのかを明確にすべきだと思います:コンテナの外側を指します。 – this

+1

@this:あなたが言うことは*ポインタ*については真実であるが、イテレータ*については必ずしもそうであるとは限りません。反復子は必ずしもポインタではありません。 –

+0

問題は、私の理解では、たとえあなたが逆参照しても問題ではないということです。私たちは、ポインターの算術演算を実行することも、「最初から始まる」ポインターを計算することも許されません。だから、配列の先頭を指すポインタを作成するだけでは、それを作成したり、サイズを測定するなどの行為がUBであるため、逆参照しない限りOKです。または私は間違っていますか? –

2

std::reverse_iteratorインターフェイスには、元のイテレータと同じイテレータを取得するメンバー関数.baseが含まれています。私は彼らが通常やっていることは、元のイテレータをキャッシュし、演算子*オーバーロードで1だけオフセットしていると考えています。

+2

うん、[[これはlibstdC++の機能です(http://gcc.gnu.org/onlinedocs/libstdc++/libstdc++-html-USERS-3.4/stl__iterator_8h-source.html#l00150)。 –

5

(端過去1)end同様にrbegin点の結果、及びbegin同様にrendの結果(最初の項目)。逆方向反復子が逆参照されると、範囲内の前の項目への参照が返されます。

1

他の回答はよく質問に答えます。

しかし、私はまた、おそらくそれが動作し、基準を満たしている限り、舞台裏で好きなことを実装できるように、とにかく合法であるかどうか疑問です。イテレータをポインタとして実装することを選択し、それを逆参照することを選択した場合、コンパイラはそれが機能することを知る責任があります。コンパイラの作成者は、未定義のビヘイビアが何であるかを知っているので、これを行うための特別なライセンスを持っており、そのビヘイビアをあなたに直接公開しないでください。イテレータインタフェース。

+0

それは合法です。コンパイラのベンダは、自分のUBを利用することができ、常にそうしています。一般的な例は 'offset_of'マクロで、これはしばしばヌルポインタの算術演算で実装されます。 – MSalters

関連する問題