2
#include <boost/ptr_container/ptr_vector.hpp>
#include <iostream>
using namespace std;

class Derived
{
public:
        int i;
        Derived() {cout<<"Constructed Derived"<<endl;}
        Derived(int ii):i(ii) {cout<<"Constructed Derived"<<i<<endl;}
        ~Derived() {cout<<"* Destructed Derived"<<i<<endl;}
};

int main()
{
   boost::ptr_vector<Derived> pv;
   for(int i=0;i<10;++i) pv.push_back(new Derived(i));

   boost::ptr_vector<Derived>::iterator it;
   for (it=pv.begin(); it<pv.end();/*no iterator increment*/ )
        pv.erase(it);
   cout<<"Done erasing..."<<endl;
}

2 番目の for ループは反復子をインクリメントしませんが、反復してすべての要素を消去することに注意してください。私の質問は次のとおりです。

  1. 私の繰り返しのテクニックとイテレータの使用は正しいですか?
  2. for ループで反復子のインクリメントが必要ない場合、インクリメントはどこで発生しますか?
  3. イテレータを使用する方が良いですか、それとも通常の整数で十分ですか (つまり、イテレータを使用して付加価値はありますか)? (pv.erase(pv.begin()+5); のように 5 番目の要素を消去することもできます)
  4. 新しいオブジェクトを ptr_vector の特定の位置 (5 番目の位置としましょう) に直接割り当てる方法はありますか? pv[5]=new Derived(5); のようなものを探しています。それを行う方法はありますか?
4

2 に答える 2

3

Aptr_vector::iteratorは、通常のランダム アクセス イテレータと同じようにインクリメントします。あなたの例では、要素を消去した後、それ以降のすべての要素が配列内で移動されるため、実際にインクリメントせずにすべての要素を消去できます。したがって、0 番目の要素を消去すると、イテレータは、以前は 1 番目の要素だったが、現在は 0 番目の要素になっている要素を指すようになります。言い換えれば、ベクトル全体が左にシフトしている間、反復子は所定の位置にとどまります。

これは特に ptr_vector とは関係ありません。プレーンでも同じ動作が発生することに注意してくださいstd::vector

また、イテレータが指す要素を消去した後にイテレータを使用することは危険です。あなたの場合はうまくいきますが、戻り値を取る方が良いptr_vector::eraseので、有効であることが保証されている新しいイテレータを取得します。

 for (it = pv.begin(); it != pv.end(); )
        it = pv.erase(it);

他の質問について:

特定の要素だけを消去したい場合は、もちろん を使用して直接消去する必要がありますpv.erase(pv.begin() + N)。ポインター ベクトルの特定の要素に新しい値を割り当てるには、単純にpv[N] = Derived(whatever). 値を再割り当てするときに使用する必要はありませんnew。ポインター ベクトルは、新しい値を割り当てるインデックスでオブジェクトの代入演算子を呼び出します。

于 2010-10-23T09:44:42.017 に答える
1

私の繰り返しのテクニックとイテレータの使用は正しいですか?

いいえ、コンテナから消去すると、通常、消去されたアイテムへのイテレータが無効になります。機能する場合、これは実装の詳細の単なる副作用です。

正しい方法は、erase メソッドの戻り値を使用することです。

 it = pv.erase(it);

ただし、コンテナーを空にするには、clear メンバー関数を使用できます。

for ループで反復子のインクリメントが必要ない場合、インクリメントはどこで発生しますか?

コンテナー内の最初のアイテムを常に消去するため、発生しません (たまたま、他のコンテナーではうまくいかない可能性があります)。

イテレータを使用する方が良いですか、それとも通常の整数で十分ですか (つまり、イテレータを使用して付加価値はありますか)? (だって のように 5 番目の要素を消去することもできます pv.erase(pv.begin()+5);)

ランダムアクセスコンテナーではそれを行うことができますが、それ以外の場合はできません (リストなど)。

新しいオブジェクトを ptr_vector の特定の位置 (5 番目の位置としましょう) に直接割り当てる方法はありますか? のようなものを探していpv[5]=new Derived(5);ます。それを行う方法はありますか?

ブーストリファレンスによると:

pv.replace(5, new Derived(5));

これにより、スマート ポインターで既存のポインターが返されるため、自動的に割り当てが解除されます。(これがイテレータではなくインデックスを取るのは不思議です...)。

または:

pv[5] = Derived(5);

ただし、これは格納されたオブジェクトを変更するだけで、ポインターは変更しません。

于 2010-10-23T10:13:16.927 に答える