Function std :: ref and swap not working well

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 are the values ​​of m and n not changing? Passing the value enclosed in std::ref to the INCREMENT function changes the value in the original variable (the variable in the stack frame that calls the INCREMENT function). Or, Is std::ref limited / limited usage?

+5
source share
3 answers

std::ref (and the associated std::reference_wrapper ) is a tool for very specific use cases in the standard library, and should only be used for them; if you want to use it in your places, you must understand it in detail and respect what it does.

Basically, reference_wrapper much closer to a pointer than a link. Therefore, replace the pointer with your swap function, and you will see that there is no reason to assume that it will really replace:

 void myswap(int* a, int* b) { int* temp = a; a = b; b = temp; } 
+8
source

Your code creates two temporary objects std::reference_wrapper and changes them, so they refer to different objects. All that happens is the replacement of two reference_wrapper objects, not their goals.

If you manually write what the function template generates, the reason for this behavior 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 does not change int objects, but only reference_wrapper objects.

If what you are trying to do is force myswap to take the links you need to call myswap<int&>(m, n) , you cannot emulate this with reference_wrapper . But you really have to fix myswap because it is pretty useless as it is written now.

+4
source

Your myswap takes items by value.

Essentially you are replacing two links ( std::reference_wrapper s) in the local scope of the function.

The values ​​they indicate will not change.


 template <typename T> void incrementer(T a) { ++a; } int a = 20; 

In this case, conversion to int& c occurs:

 operator T& () const noexcept { return *_ptr; } 

In your code, on the other hand:

 T temp = a; 

just call the copy constructor, which will copy the main pointer:

 reference_wrapper(const reference_wrapper&) noexcept = default; 

then on the following lines you will again copy the pointer:

 reference_wrapper& operator=(const reference_wrapper& x) noexcept = default; 
+1
source

Source: https://habr.com/ru/post/1237928/


All Articles