28

What benefits has using std::reference_wrapper as template parameter of containers instead of raw pointers? That is std::vector<std::reference_wrapper<MyClass> > vs. std::vector<MyClass*>

I like forgetting about nulls and not having to use pointer syntax, but the verbosity of the types (i.e. vector<reference_wrapper<MyClass> >) plus having the call site use std::ref to wrap the actual reference makes me think it is not worth it.

I am referring to cases in which using std::shared_ptr or any other smart pointer is not an option.

Are there other benefits of using reference_wrapper or any other factors I am currently not taking into account? (I think my question applies to both C++11's reference_wrapper and boost's)

noe
  • 1,684
  • 1
  • 17
  • 35
  • 5
    IMO, reference non-nullity is a great benefit, that often outweighs the verbosity. But this is just an opinion of a seasoned null-hater. – kkm inactive - support strike Feb 05 '12 at 13:06
  • @kkm does this argument still hold with [not_null](https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#i12-declare-a-pointer-that-must-not-be-null-as-not_null) pointers? – Rufus Feb 16 '17 at 04:08
  • @Woofas: Maybe not. I'm not very familiar with the latest language proposals. This one has been out for the whoppin' 3 days! :) – kkm inactive - support strike Feb 16 '17 at 19:52
  • 1
    "_plus having the call site use std::ref to wrap the actual reference"_ That is not required in contexts where the expected type is known and hence can use `std::reference_wrapper<>`'s implicit conversion operator to its `::type&`. – underscore_d Sep 23 '18 at 13:43

2 Answers2

26

I don't think there is any technical difference. Reference wrapper provides basic pointer functionality, including the ability to change the target dynamically.

One benefit is that it demonstrates intent. It tells people who read the code that "whoever" has the variable, isn't actually controlling its lifespan. The user hasn't forgotten to delete or new anything, which some people may start to look for when they see pointer semantics.

Philluminati
  • 2,649
  • 2
  • 25
  • 32
  • 1
    Corollary - references/ref_wrappers don't prevent object lifetime issues, even though their syntax is nicer than pointers. – mskfisher Apr 08 '15 at 14:26
  • 1
    Yes, it's all about intent indeed. I would add that references are non-null pointers. `std::vector` might have a nullptr in it, whereas when iterating over a vector of references, you know all of them are supposed to be valid. – Georges Jul 02 '17 at 17:08
  • With strong emphasis on "supposed to"... It's still quite easy to create a null reference that only causes a crash when accessing the reference's value... e.g.: `int* x = static_cast(nullptr);` `int& y = *x;` <-- doesn't crash `int*z = &y;` <-- still doesn't crash `y++;` <-- crashes – Kevin May 06 '18 at 21:56
1

C references are really problematic while working with templates. If you are "lucky" enough to compile code with reference as a template parameter you might have problems with code that would work (for some reason) as follows:

template<class T> f(T x) { g(x); }
template<class T> g(T x) { x++; }

Then even if you call f<int&>(x) it will call g<int>. But reference_wrapper works fine with templates.

As also mentioned earlier - you will have problems with compiling things like vector<int&>, but vector<reference_wrapper<int>> works fine.

Noxitu
  • 346
  • 2
  • 6
  • "Then even if you call `f(x)` it will call `g`." Yeah, I think this is because you didn't take the argument to `f()` as a forwarding reference and then `std::forward` it to `g()`. I think if you did that, you could make this work. If so, missing a step when coding doesn't make the language "really problematic". ;-) – underscore_d May 20 '17 at 19:17