Jump to content
• Advertisement

Public Group

The advantage of iterators?

This topic is 4392 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Been using iterators for a fair while now, but I don't know why. I mean... they're supposedly the "right" way to scan a vector, but I don't exactly get why. They also seem to be less versatile than using a loop with the [] operator or at function. Like let's have 2 examples... say you want to delete an int in a vector if it is equal to 5.
//iterator way!
for (it=vec.begin();it!=vec.end();it++)
{
if(*it == 5)
vec.erase(it);
}
/* Now that the iterator points to nothing, next round it'll try pointing to something that isn't in the vector and not initialized... program pukes */
int pos = 0;
for (int it=0;it!=vec.size();it++)
{
if(vec[it]==5)
pos = it;
}
if(pos)
vec.erase(pos);

And since you don't know what position an iterator is pointing to, can't really do that with them. Anyways, that's not my main point... just curious what the huge advantage over them is. :) -Etyrn

Share this post

Share on other sites
Advertisement
You can A:
for ( it=vec.begin();it!=vec.end;){if ( *it == 5 )   it = vec.erase(it);else   ++it;}

or
vec.erase(remove_if( vec.begin(), vec.end(), bind2nd(equal_to<int>(),5) ) );

Iterators can be aquward for some situations, but when you are using any STL constuct, they take interators,
so it is the way to go.

Share this post

Share on other sites
^^ Edit: You got fist! Umm..... first! :)

That's why erase() returns an iterator to the next object in the vector. :)

it = vec.erase(it);

Iterators are faster (they are pretty much a pointer, but to use [] is a lookup:

pointer + i * sizeof(object)

They are also more flexible, as they can be used in all of the STL algorithms.

Share this post

Share on other sites
Thank you. You were both very helpful. :)

-Etyrn

Share this post

Share on other sites
bool is5(int n){    return(n==5);}vec.erase(remove_if(vec.begin(),vec.end(),is5),vec.end());

Share this post

Share on other sites
Additionally, not all of the standard library containers allow you to access their elements with the [] operator. For example:

#include <set>#include <iostream>int main(){    std::set<int> foo;    foo.insert(1);    foo.insert(5);    foo.insert(3);        // Doesn't work because elements in a std::set can't be accessed with the [] operator    // for (unsigned int i = 0; i < foo.size(); ++i)        // std::cout << foo << std::endl;    // Works    for (std::set<int>::iterator itor = foo.begin(); itor != foo.end(); ++itor)        std::cout << *itor << std::endl;    // If you won't be changing any of the elements, using a const_iterator is smarter     for (std::set<int>::const_iterator itor = foo.begin(); itor != foo.end(); ++itor)        std::cout << *itor << std::endl;}

Share this post

Share on other sites
Quote:
 Original post by TANSTAAFL *** Source Snippet Removed ***

After reading your example, I didn't really like the is5... so I tried something and it seems to work (at least with VC 2005, since its a template trick, it probably doesn't work on old compilers)

template<class T, T value> bool isValue(T in_Value){	return (value == in_Value);}

so later on in your code (this is just an example...)

typedef std::vector<int> idvectors;idvectors myvect;// ... push values heremyvect.erase(std::remove_if(myvect.begin(),myvect.end(),isValue<idvectors::value_type,5>),myvect.end());

the only downside is that "5" needs to be known at compile time, and it will generate something similar to is5, but I thought it was cleaner this way, and supports any type that has == defined :)

Cheers!

Eric

Share this post

Share on other sites
a predicate is simply something that has operator (). you can make a class to do the job:

class compare_to_value{private:    int m_compare_to;public:    compare_to_value(int compare_to):m_compare_to(compare_to){}    bool operator()(int value){return(value==m_compare_to);}};int n=5;myvect.erase(std::remove_if(myvect.begin(),myvect.end()),compare_to_value(n)),myvect.end());

and you could, to make compare_to_value more reusable, make it a template class as well. I just used an int because templates make my headasplode.

Share this post

Share on other sites
Quote:
 Original post by KulSeranvec.erase(remove_if( vec.begin(), vec.end(), bind2nd(equal_to(),5) ) );

The standard library recognizes that this is unnecessarily verbose and the extra weight of generated code might not all get optimized away, so it also provides the simpler version for the case of checking for equality:

vec.erase(remove( vec.begin(), vec.end(), 5 ) );

:)

Anyway:

- Iterators protect you from changes to the container type, since not all of them allow you to use operator[], and some (std::map) use operator[], but don't necessarily use it with integers in order (std::map::operator[] expects key types). With an appropriate typedef, you end up being protected from changing the code if you change the type of the container that is iterated over:

typedef std::vector<int> container;// Later, we change that to std::list<std::string>, and the loop still compiles:container x;// ...for (container::iterator it = x.begin(); it != x.end(); ++it) {  cout << *it << endl;}

- They also clean up the abstraction a little bit: Instead of "with every number in this range, grab the element at this index, and do stuff with it", you get "with an element-pointer ranging over the collection, do stuff with each element as it is pointed at". It's not as nice as the higher-level looping constructs in Python (or even C# or Java 1.5), but it's an improvement. The reason you do that is the same reason you use for() in the first place instead of reproducing that behaviour with while(), or in turn why you use while() instead of reproducing it with goto(s).

- However, for common types of looping, you should use the std::algorithm (or combination thereof) that best models what you want to accomplish.

Share this post

Share on other sites
Yeah that's nice! I never used a class as a predicate, seems pretty flexible, thanks for the tip!

Share this post

Share on other sites

• Advertisement

Announcements

• Advertisement
• Popular Tags

• Advertisement

• 47
• 12
• 10
• 10
• 9
• Forum Statistics

• Total Topics
631373
• Total Posts
2999643
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!