2011-12-07 10 views
1

以下は、http://www.sgi.com/tech/stl/copy.htmlによるcopyの定義です。STLコピーの実装

template<class InputIterator, class OutputIterator> 
    OutputIterator copy (InputIterator first, InputIterator last, OutputIterator result) 
{ 
    while (first != last) *result++ = *first++; 
    return result; 
} 

次のコードを書きました。

vector<int> v; 
set<int> s; 

s.insert(7); 
s.insert(11); 
s.insert(27); 

//copy elements from the set into the vector 
copy(s.begin(), s.end(), v.begin()); 

なぜ上記のコピーを呼び出すと、実行時エラーは発生しますが、コンパイルエラーは発生しません。私は、ベクトルが空であるという事実、v.begin()== v.end()と関係があると仮定しています。しかし、なぜ?

また、コードを次のように変更して修正しました。

copy(s.begin(), s.end(), back_inserter(v)); 

機能back_inserterは、タイプback_insert_iterator>のイテレータを返します。なぜこれは機能しますか?それは何ですか?

答えて

2

あなたはこの同じサイトに記載されている第三の前提条件尊重していないので、それが失敗した:

コピーされているすべての要素を保持するのに十分なスペースがあります。 正式には、[result、result +(last-first))は の有効範囲です。 [1]

空のベクトルは3要素の集合よりも小さいので、コピー操作は実行できません(本当に "上書き"操作と呼ばれる)。この情報はコンパイル時には分かりません。したがって、コンパイル時にエラーは発生しません。ベクトルや他のほとんどのC++ STLコレクションは実行時に展開可能ですが、通常はイテレータの通常の操作(アイテムの列挙や範囲の指定を目的としています)で展開することはできません。

関数back_inserterは、要素をコレクションの最後に挿入する特殊なイテレータを返します。このイテレーターは出力イテレーターであり、ベクトルのbegin()end()メソッドで取得できるイテレーターとはほとんど関係がありません。出力イテレータから読み込むことはできません。

0

単純な配列の場合を考えてみましょう。イテレータのポインタを使用します。今、sとvが配列であると想像してください。 sが3要素とv 0を持っていて、sをvにコピーしようとすると、うまくいきません。しかし、vが3つの要素を持つ場合、コピーは動作し、現在の内容を上書きします。

STLのイテレータモデルはこれを一般化したものです。実際、ポインタはイテレータとして使用できますが、他のオブジェクトも使用できます(copyには配列の最初の要素へのポインタを、もう1つのポインタには末尾のポインタを指定しても動作します)。したがって、正確に同じ理由で機能しません。

back_inserterは、この場合のためのイテレータです。現在の位置を上書きしてコレクションを移動するのではなく、コレクションのサイズを増やします(ベクターのように大きくなるコレクションでなければなりません)。

関連する問題