8

イテレータのペアを取る関数があります。空の範囲が渡されたかのように動作する引数なしバージョンの関数を提供したいと思います。

具体的に言うと、最初の関数は次のとおりです。

void f(vector<int>::iterator b, vector<int>::iterator e) { // impl. }

私はこれを書きたい:

void f() { f({}, {}); }

ここで初期化は正しいですか? (コンパイルします)。

等しいイテレータのペアを取得するには、コンテナを作成する必要がありますか?

4

2 に答える 2

7

私の理解では、これは標準に準拠した方法では一般的に行うことはできません。

24.2.1/5 :

イテレータは、どのシーケンスにも関連付けられていない特異値を持つこともできます。[ 例: 初期化されていないポインター x (int* x; と同様) の宣言の後、x は常にポインターの特異値を持つと想定する必要があります。— 例の終了]ほとんどの式の結果は、特異値に対して未定義です。唯一の例外は、特異値を保持する反復子の破棄、特異値を保持する反復子への非特異値の代入、および以下を満たす反復子の場合です。DefaultConstructible値で初期化された反復子をコピーまたは移動操作のソースとして使用します。[ 注: この保証は、デフォルトの初期化には提供されませんが、この区別は、ポインターやポインターを保持する集約などの単純なデフォルト コンストラクターを持つ型に対してのみ重要です。— 終わりの注 ] これらの場合、特異値は他の値と同じ方法で上書きされます。逆参照可能な値は常に特異ではありません。

デフォルト/値の初期化は明らかにどのシーケンスにも関連付けられていないため、Iterator は特異です。2 つの特異な Iterator の比較は未定義の動作です。

std::vector<int>::iterator i;
std::vector<int>::iterator j = i; // UB, assignment of a non-a singular value
                                  // If you pass `i` to a function, a copy is done
                                  // which also results in UB (as in Andy's answer).

次の試行では、値の初期化を使用します

std::vector<int>::iterator i{};
std::vector<int>::iterator j = i; // ok, i is value-initialized
i == j; // undefined, comparison is not explicitly non-undefined behavour
i == i; // undefined, comparison is not explicitly non-undefined behavour 

についてこれ以上の情報がないためvector<int>::iterator、あなたのアプローチは間違っています。

あなたができることはf、テンプレートに変更してポインターを使用することです:

template <typename Iter>
void f(Iter b, Iter e);

int *p; f(p, p); // ok, defined for pointers
于 2013-03-28T22:39:13.013 に答える
1

イテレータのデフォルトのコンストラクタは常にend. とはいえ、同じ反復子を関数に渡すと、定義上、それも空の範囲になります。

static_cast<int*>(NULL)すべてのポインターは有効な反復子であるため、両方の引数として使用できるはずです。(またはvector<int>::iterator())。

于 2013-03-28T22:07:57.600 に答える