Using begin() and end() with a set in c++
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 th开发者_StackOverflow中文版e 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.
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++)
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.)
精彩评论