26

In c++ primer, pg 95 the author says that c++ programmers tend to use != in preference of < when writing loops.

for (vector<int>::size_type i = 0; i != 10; ++i) is preferred instead of 
for (vector<int>::size_type i = 0; i < 10; ++i) 

I read the same thing in accelerated c++. Can someone explain the rationale behind this

6
  • 7
    Whoever writes the above code must be executed. See blogs.csoonline.com/node/151 Commented Dec 25, 2010 at 20:04
  • 2
    @ybungalobill: good article, bad conclusions :) Commented Dec 25, 2010 at 20:10
  • 1
    @Kos: just joking :) and of course it's not so critical in a for loop. Commented Dec 25, 2010 at 20:11
  • 2
    If the author of the book is to be believed, then what is the correct comparison operator when incrementing like: i+=2 or i+=7 etc....? another stupid generalization of the type defined as the following: "Those who can, do; those who can't, teach or author crappy c++ books" :D Commented Dec 25, 2010 at 22:43
  • 2
    @Zenikoder: stupid generalization indeed. Maybe you should've read the book and you'd have understood both the context of the "rule" and the rationale behind it. Instead, of course, it is oh so much easier to take it out of context and spew some generic crap about how clueless some of the world's best c++ programmers must be. I don't suppose you noticed the word "preference" in the question? No one suggested using != when it yields in correct code. Just that when both will do the job, C++ programmers have reason to prefer != Commented Dec 26, 2010 at 7:39

7 Answers 7

44

When using some kinds of STL iterators (those that aren't random access), you must use !=:

for (map<int,int>::iterator i = a.begin(); i != a.end(); ++i) ...

However, I don't see any reason to prefer != for well-ordered scalar types as in your example. I would usually prefer < for scalar types and != for all iterator types.

Sign up to request clarification or add additional context in comments.

9 Comments

Well I guess the reason would be so that all your for loops read the same
Correction: when using STL iterators, except random-access ones, you must use !=. So in case of vector<int>, < is fine.
You do not have to use != for all STL iterators. Random access iterators will work just as well with <.
Also, you should use != unless you must use <. See C++ Coding Standards, item 67. Using < needlessly is unnecessarily ungeneric and a premature pessimisation.
@ltjax - Where are these hypothetical coding standards you mention? Personally, I prefer programming defensively to making sure I can randomly change the type of a loop variable. I suppose if I were using auto that might change.
|
31

It's a habit for generic programming; for example, you can easiely use < with indices, but you cannot use that with all iterator types. A list iterator cannot efficiently implement < - however, != can be implemented for even the simplest of iterator types. Therefore, it is a good habit to always use the most generic comparison - it makes your code more resilient to change.

Comments

11

Think of the case when one have to increment by lets say 3 instead of 1.

for (vector<int>::size_type i = 0; i != 10; i+=3)

This will run forever since it will skip 10 and go to 12 instead and increment forever.

for (vector<int>::size_type i = 0; i < 10; i+=3) 

This will work fine in this case too. So != is not always a good choice.

4 Comments

Actually the first one will stop on a binary computer, that's because 3 is a generator of the ℤ/2^nℤ group.
Err.. this is true, but it really doesn't answer the question asked.
This is just a counter-argument for the usage of !=
It's not really a counter argument: using != protects the code against long range changes - i.e. when you change the type of the container/range you're using. Using < only protects you against changes of the actual iteration step, which have to happen in that very same line.
8

Because, in general, not all iterators support the "<" operation. See the manual for operation supported by each iterator type. Only random access iterators (of which, simple pointers are a subset) support inequality comparisons (< and >) between iterators

Comments

7

If you write !=, then you can reverse the loop iteration with minimal change.

Suppose you first write:

for ( int i = m; i != n ; i++ )

Later you reverse it:

for ( int i = n ; i != m ; i-- )

Not so appealing, but still it requires less analysis than "<" and ">".

2 Comments

However, the first loop will cover the range [m, n) while the second will cover (m, n].
@itjax: Nice catch. I didn't notice that. thanks for pointing out it :-)
7

The requirement of being "relationally comparable" is a much stronger one than the requirement of being "equally comparable". When it comes to iterating over containers, the possibility to perform relational comparison between iterators or generic indices (like <, >, <= etc.) is strongly associated with random-access containers, while the equality comparisons are more universally applicable (and often the only ones available when working with sequential access containers).

In general, it is a good practice to make you code as generic as possible, i.e. you should never rely on stronger requirements when weaker requirements are perfectly sufficient. In other words, if you can implement your algorithm by using equality comparisons only, it is better to do it that way, without bringing in any relational comparisons. It is possible that way you will make your algorithm more usable with a wider range of underlying data structures (containers).

Of course if you don't care about this kind of genericity or simply don't need it, you can just ignore these considerations and use either approach.

1 Comment

+1 for rationalising on a mathematical basis, particularly for "you should never rely on stronger requirements when weaker requirements are perfectly sufficient".
0

Maybe those who preffer this is because they got used to checking for null, etc... so preffer use the same != in everything.

if(x != null) { ... }

for(int i=0; i != 10; i++) { ... }

so for those everyting tends to be != or ==

read != as DIFFERENT/NOT EQUAL, following the same principle as == is EQUAL,

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.