Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the normal convention for naming and using iterators in C++?

I feel like I'm unprofessional in the way I name and use iterators. What I mean by that is that I "feel" like I should be calling them something else, but I always name them based on the "it_" prefix, and after a while, in a long function, the names start to all look alike.

Additionally, I always wonder if I'm doing things a "strange" way that I learned just because I didn't know better. For instance, if I were iterating through a map to display all its key/value pairs, I would do this:

map<int, int>::const_iterator it = layout.begin();
for (; it != layout.end(); ++it)
{
   cout << it->first << ":\t" << it->second << "\n";
}

I see some people calling their iterators "iter" - I see other ways of doing loops. Is there any kind of convention that transcends style and is just good practice?

like image 310
Tim Avatar asked Sep 29 '10 23:09

Tim


2 Answers

I haven't seen a single canonical loop.

The cost of creating an iterator is specified to be O(1) (wrt the size of the container), but it may cost, especially when specific debugging options are activated.

Therefore, calling end at each iteration of the loop is wasteful.

The canonical way to write a for loop is therefore to compute both it and end in the first statement.

typedef std::map<int,int> LayoutType;

for (LayoutType::const_iterator it = layout.begin(), end = layout.end();
     it != end; ++it)
{
  // ...
}

I usually typedef my container, but honestly there isn't much point in typedefing the iterator, it's already available within the container and introducing too many synonyms does not help.

Also, it may be a personal quirk, but I prefer stating the function rather than the type when I introduce my typedef. The type may change in later refactoring, the function will not (at least, it won't be the same thing at all if it does, so it'll call for a complete rewrite).

For example what if you suddenly preferred: typedef std::unordered_map<int,int> LayoutType ? It still matches your need, and you can probably drop it in at no rewriting cost (providing you have used a typedef).

like image 35
Matthieu M. Avatar answered Sep 28 '22 08:09

Matthieu M.


I try to declare the iterators inside the for loop as much as possible, so that the scope of the iterator identifier is minimized.

First, I typedef the "long" type names to "shorter" and re-usable ones:

typedef std::map< int, int > IntMap;
typedef IntMap::const_iterator IntMapConstIter;

Then, I do

for( IntMapConstIter it = layout.begin(); it != layout.end(); ++it ) {
    ....
}
like image 137
Arun Avatar answered Sep 28 '22 06:09

Arun