Reputation: 197
I've got two questions regarding comparison operators in C++:
mdata
and mfirst_free
is double*
, too):for (double *p = mdata; p < mfirst_free; ++p) { .. }
for (double *p = mdata; p != mfirst_free; ++p) { .. }
I'll guess in the advance the same answer is valid for all primitive types - int
, double
, and pointers. Right?
I know <
version is safer because if I somehow start with bigger pointer than expected it won't be infinite loop. But, when I'm sure I won't get invalid input, which version is more efficient?
Let's take hypothetical situation of trying to save every processor cycle - what are the best choices? Are there some that are others more elegant?
Upvotes: 0
Views: 182
Reputation: 74018
As always, see for yourself and look at the generated code. With g++ 4.8 on Ubuntu 14.04, you get
movq -16(%rbp), %rax
movq %rax, -32(%rbp)
jmp .L2
.L3:
addq $8, -32(%rbp)
.L2:
movq -32(%rbp), %rax
cmpq -8(%rbp), %rax
jb .L3
movq -16(%rbp), %rax
movq %rax, -24(%rbp)
jmp .L4
.L5:
addq $8, -24(%rbp)
.L4:
movq -24(%rbp), %rax
cmpq -8(%rbp), %rax
jne .L5
As you can see, the only relevant difference is jb .L3
vs jne .L5
.
So, I would say both are equivalent from a performance point of view.
Answering the second question, the minimum necessary for comparison is operator<
. You can deduce everything else from this, e.g.
bool operator==(const T &x, const T &y) {
return !(x < y) && !(y < x);
}
bool operator!=(const T &x, const T &y) {
return !(x == y);
}
bool operator>(const T &x, const T &y) {
return y < x;
}
bool operator<=(const T &x, const T &y) {
return !(y < x);
}
bool operator>=(const T &x, const T &y) {
return !(x < y);
}
Of course, this is only true if you have the usual comparison semantics.
Upvotes: 5
Reputation: 9092
If the counter variable is an integer or pointer, there is probably no difference in efficiency. The effect is the same as long as the variable is just being incremented (by one) and start out smaller or equal and the end value.
But C++ iterators don't necessarily implement operator<
. In fact only RandomAccessIterator
are required to do so (see http://en.cppreference.com/w/cpp/iterator). So C++11 translates for(auto&& v : values)
to for(auto it = std::begin(values); it != std::end(values); ++it)
. For example std::forward_list
only has ForwardIterators
and so operator<
can't be used to iterate through it.
If you use OpenMP for parallelization operator<
is needed:
#pragma omp parallel for
for(auto it = std::begin(values); it < std::end(values); ++it)
Because it needs to split the loop into smaller loops.
I guess in general it would be best to use operator!=
to be compatible with all iterator types, unless you do something else than iterate (increment by more than one, etc.), use floating point values as counter, or use OpenMP.
Upvotes: 1
Reputation: 619
As far as I know, it really doesn't make a difference. I believe that
p != mfirst_free
would be translated to something in assembly similar to
loop
CMP p mfirst_free
BEQ exit
{...body...}
B loop
exit
while the
p < mfirst_free
would translate to the same, but instead of a BEQ instruction it would be a BGE. Same number of instructions take would take the same amount of time to be executed.
-There are various ways to translate a for loop to assembly, but my point here is that every comparison operator that you use would lead to the same running time, as far as I know.-
Upvotes: 1
Reputation: 69854
First of all, in pure c++ terms there is no correct answer to your question since the standard does not specify it and it's left to the compiler and CPU's discretion.
In real terms you're asking whether a 'branch if not equal' instruction takes any less time than a 'branch if less' instruction. In all CPUs I have ever encountered the answer will be 'no' - provided you don't get wrong-footed by incorrect branch prediction.
Upvotes: 2