iter_swap() versus swap() -- what's the difference?
The standard itself has very few mentions of iter_swap
:
- It should have the effect of
swap(*a, *b)
, although there is no stipulation that it must be implemented that way. - The dereferenced values
*a
and*b
must be "swappable", which implies thatswap(*a, *b)
must be valid, and thus the dereferenced types must be identical, although the iterator types do not have to be. iter_swap
is required to be used in the implementation ofstd::reverse
. No such requirement is placed on any other algorithm, so this seems to be an oddity.
To borrow what sehe had found from the SGI docs:
Strictly speaking,
iter_swap
is redundant. It exists only for technical reasons: in some circumstances, some compilers have difficulty performing the type deduction required to interpretswap(*a, *b)
.
All of these seem to suggest that it is an artifact of the past.
What's the point of iter_swap?
From the SGI docs (here):
[1] Strictly speaking, iter_swap is redundant. It exists only for technical reasons: in some circumstances, some compilers have difficulty performing the type deduction required to interpret swap(*a, *b).
std::iter_swap requires ValueSwappable args vs std::swap requires Move Assignable args
The swap
called inside iter_swap
is not fully qualified i.e not called as std::swap
but just as swap
. Therefore, during name lookup and ADL
compiler finds multiple functions which matches with the call to swap
. But, the overload resolution
selects the swap
provided by you since it matches best.
If you use swap
in your main code, then it would compile fine as it would not find std::swap
. It will compile even if you do using namespace std;
Why/when should we prefer using std::swap; swap(a, b) over std::iter_swap(&a, &b)?
3 years later, but I believe the only technical concern would be if operator &()
is overloaded.
If not, the only other reason I see would be readability.
Is this way of swapping 2 numbers better or worse than the one that uses a temp variable?
You should say what language you are using first of all.
In general I think its safe to say that "in-place swap" is preferable, from a performance standpoint, to swapping using a temporary.
In C or C++ the above is not good because if you cause integer overflow you get undefined behavior.
In those languages it's better to use bitwise operations for this. The basic observation is that if A and B are bits and we use addition modulo 2, then this is a swap (pseudocode):
a += b;
b += a;
a += b;
// Now A and B are swapped if they are numbers mod 2.
In C / C++ you would therefore use bitwise XOR in the above pattern, to do it to all of the corresponding bits at once.
I believe that's how e.g. the standard swap implementation for two pointers is implemented. (OTOH it's possible that this could just happen as a compiler optimization)
It has the benefit that the in-place version can't fail, while the version that uses a temporary variable can potentially blow the stack if the objects being swapped are too large.
The XOR swap is also substantially better than the naive swap implementation if a
and b
are smart pointer types -- creating a temporary smart pointer could cause allocations, call a user defined constructor, have side effects, and potentially throw exceptions, meaning that the swap is no longer a no-fail, noexcept
function. The XOR swap avoids all of that.
Incremented iterator std::next when swapping
In the first code, the order of evaluation of the two ops *i
and *(++i)
unspecified after c++17, hence the second one may execute before the first, and then the swapping swaps two equivalent values.
In the attached link, u can see that
f(++i, ++i); // undefined behavior until C++17, unspecified after C++17
But in the second code you have different parameters and std::next()
returns a new iterator.
Related Topics
"Proper" Way to Store Binary Data with C++/Stl
Link Error "Undefined Reference to '_Gxx_Personality_V0'" and G++
Check If One String Is a Prefix of Another
How to Convert a Const Char * to Std::String
Localtime VS Localtime_S and Appropriate Input Arguments
Cross-Platform Iteration of Unicode String (Counting Graphemes Using Icu)
Differencebetween Std::Quick_Exit and Std::Abort and Why Was Std::Quick_Exit Needed
How to Store Array in One Column in SQLite3
What Is the Performance Impact of Using Int64_T Instead of Int32_T on 32-Bit Systems
Why Can't I Inherit from Int in C++
Which Is Faster/Preferred: Memset or for Loop to Zero Out an Array of Doubles
A Simple Hello World Npapi Plugin for Google Chrome
How to Initialize All Elements in an Array to the Same Number in C++