简体   繁体   中英

std::reference_wrapper v.s. int&

I was trying out the std::reference_wrapper with the following snippet

int a = 42, b = 52;
std::tuple<std::reference_wrapper<int>> t = std::make_tuple(std::ref(a));

std::get<0>(t) = b;
std::cout << "t[0] = " << std::get<0>(t) << ", a = " << a << ", b = " << b
          << std::endl;

The output is t[0] = 52, a = 42, b = 52 , which not surprising.

However, if I just use auto for t , namely

int a = 42, b = 52;
auto t = std::make_tuple(std::ref(a));

std::get<0>(t) = b;
std::cout << "t[0] = " << std::get<0>(t) << ", a = " << a << ", b = " << b
          << std::endl;

Then I got t[0] = 52, a = 52, b = 52

Looks like the type becomes int& . Then I have some questions:

  1. I thought std::ref gives us std::reference_wrapper rather than & ?
  2. How I should explain the case of & and why it is different from std::reference_wrapper .
  3. I also noticed that, in the case of std::reference_wrapper , std::get<0>(t) = 52; does not compile. (While in the case of & it does). the error is "calling a private constructor of class 'std::__1::reference_wrapper'". Could someone explain that in more detail?

Thanks!!

  1. I thought std::ref gives us std::reference_wrapper rather than &?

That's not a question, but you thought correctly.

  1. How I should explain the case of & and why it is different from std::reference_wrapper.

When a std::reference_wrapper argument passed to std::make_tuple , the resulting tuple will have a reference member rather than a reference wrapper.

The difference in behaviour is because when you assign a reference, you modify the referred object while when you assign a reference wrapper, you instead rebind the wrapper to refer to another object and don't modify the referred object.

I also noticed that, in the case of std::reference_wrapper, std::get<0>(t) = 52; does not compile. (While in the case of & it does). the error is "calling a private constructor of class 'std::__1::reference_wrapper'". Could someone explain that in more detail?

std::reference_wrapper doesn't have an assignment operator for the referred type. It only has assignment operator for another reference wrapper. std::reference_wrapper has an implicitly converting constructor that accepts an lvalue, but not one that accepts an rvalue.

That is why you can assign b which is an lvalue, but cannot assign 52 which is a prvalue. This is a good thing because the lifetime of the temporary object cannot be extended by the reference wrapper.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM