template <typename T>
void myswap(T a,T b)
{
T temp = a;
a = b;
b = temp;
}
int main()
{
int m(20),n(30);
myswap(ref(m),ref(n));
//m is still 20 and n is still 30
}
Why have not the values of m and n interchanged? Passing a value wrapped in std::ref
to an INCREMENT function results in value change in the original variable (variable in the stack frame that calls INCREMENT function). Or, Is std::ref
usage is restricted/limited?
std::ref
(and its associated std::reference_wrapper
) is a tool designed for very specific use cases in the standard library and should only be used for those; if you want to use it in your own places, you have to understand it in detail and respect what it does.
Fundamentally, a reference_wrapper
is much closer to a pointer than a reference. So substitute a pointer in your swap function and you'll see that there's no reason to assume that it would actually swap:
void myswap(int* a, int* b)
{
int* temp = a;
a = b;
b = temp;
}
Your code creates two temporary std::reference_wrapper
objects and swaps them, so they refer to different objects. All that happens is you swap two reference_wrapper
objects, not their targets.
If you manually write what the function template will generate the reason for the behaviour should be obvious:
void myswap(std::reference_wrapper<int> a, std::reference_wrapper<int> b)
{
std::reference_wrapper<int> temp = a;
a = b;
b = a;
}
Obviously this doesn't change the int
objects, only the reference_wrapper
objects.
If what you're trying to do is force myswap
to take references you need to call myswap<int&>(m, n)
, you can't emulate that by using reference_wrapper
. But you should really fix myswap
, because it's pretty useless the way it's written now.
Your myswap
takes the elements by value.
Essentially you swap the two references (std::reference_wrapper
s) at the local scope of the function.
The values they point to won't change.
template <typename T> void incrementer(T a) { ++a; } int a = 20;
In this case there's a conversion to int&
with:
operator T& () const noexcept { return *_ptr; }
In your code, on the other hand:
T temp = a;
will simply call the copy constructor, which copies the underlying pointer:
reference_wrapper(const reference_wrapper&) noexcept = default;
then, on the next lines you again copy the pointer:
reference_wrapper& operator=(const reference_wrapper& x) noexcept = default;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With