Domanda

I am trying use an iterator to go through a set and then do something with the members of that set(if there are any). The problem is that, normally this works, but sometimes, it compares the beginning and the end of an empty set and finds them not to be equal.

The code snippet of interest is:

    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);  
        }
    }

Sometimes, even though the set contained in verlet_vars.verlet()[i] is empty, the program compares the iterator to the end of the set and finds them not equal, and so it enters the inner loop(ultimately causing the program to crash by trying to call the force() function). What is bizarre is if I do anything with the iterator before the inner loop is called,like doing something like:

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

then, the comparison for the inner loop always returns true, and the program runs normally.

P.S. the command verlet_vars.verlet()[i] calls a vector of sets, hence the [i]

The verlet() function:

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

Thanks for your time.

È stato utile?

Soluzione

Your verlet_vars.verlet() function returns by value, so you actually have two different vectors of sets in play. Comparing iterators of two different containers is undefined. That means it's possible for some arrangements of code to appear to always work, but you're still just lucky if it does.

Some alternatives:

  • Make the function return a vector reference instead:

    std::vector<std::set<int> > const& verlet() const {return _verlet;}
    
  • Call the function once to get a local copy of the vector (or the set) and then work off the local copy during the loop:

    std::set<int> verlet_i = verlet_vars.verlet()[i];
    set<int>::iterator iter;
    for(iter=verlet_i.begin();iter!=verlet_i.end();iter++)
    

Altri suggerimenti

It may not be of importance, depending on whether your compiler does copy or not the returning value. You should be using a const reference on the return type of verlet(). If not, you may end up receiving a different copy with each call, that (depending on the implementation) may cause the iterators not being compared exactly (for instance, comparing an iterator of a set with the end iterator of another set, because each time you call verlet() you get a different copy of the set.)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top