1

イテレータを使用してセットを通過し、そのセットのメンバーで何かをしようとしています(存在する場合)。問題は、通常はこれが機能することですが、空のセットの最初と最後を比較して、それらが等しくないことが判明することがあります。

対象のコード スニペットは次のとおりです。

    for(int i=0;i<input_data.num_particles();i++)
    {
        //loop through pairs contained in particle i's Verlet list
        set<int>::iterator iter;
        for(iter=verlet_vars.verlet()[i].begin();iter!=verlet_vars.verlet()[i].end();iter++)
        {
            //call the force() function to calculate the force between the particles
            force(particles.getpart(i),particles.getpart(*iter),input_data,*iter);  
        }
    }

verlet_vars.verlet()[i] に含まれるセットが空であっても、プログラムは反復子をセットの末尾と比較し、それらが等しくないことを検出し、内部ループに入ります (最終的にプログラムがクラッシュします)。 force() 関数を呼び出そうとすることによって)。奇妙なのは、内部ループが呼び出される前にイテレータで何かを行う場合です。たとえば、次のようにします。

iter=verlet_vars.verlet()[i].begin();

その後、内側のループの比較は常に true を返し、プログラムは正常に実行されます。

PS コマンド verlet_vars.verlet()[i] はセットのベクトルを呼び出すため、[i]

verlet() 関数:

std::vector<std::set<int> > verlet() const {return _verlet;}

御時間ありがとうございます。

4

2 に答える 2

8

関数verlet_vars.verlet()は値によって返されるため、実際には 2 つの異なるセットのベクトルが使用されています。2 つの異なるコンテナーの反復子の比較は未定義です。つまり、コードの配置によっては常に機能しているように見える可能性がありますが、機能する場合でも幸運です。

いくつかの代替案:

  • 関数が代わりにベクトル参照を返すようにします。

    std::vector<std::set<int> > const& verlet() const {return _verlet;}
    
  • 関数を 1 回呼び出してベクター (またはセット) のローカル コピーを取得し、ループ中にローカル コピーを処理します。

    std::set<int> verlet_i = verlet_vars.verlet()[i];
    set<int>::iterator iter;
    for(iter=verlet_i.begin();iter!=verlet_i.end();iter++)
    
于 2011-08-29T21:40:06.110 に答える
0

コンパイラが戻り値をコピーするかどうかによっては、重要ではない場合があります。の戻り値の型で const 参照を使用する必要がありverlet()ます。そうでない場合は、呼び出しごとに異なるコピーを受け取ることになり、(実装によっては) イテレータが正確に比較されない可能性があります (たとえば、セットのイテレータを別のセットの最後のイテレータと比較するなど)。お電話verlet()いただくと、セットの別のコピーを取得できます。)

于 2011-08-29T21:42:44.043 に答える