Reference Wrappers Explained

Wednesday, 14 July 2010

The upcoming C++0x standard includes reference wrappers in the form of the std::reference_wrapper<T> class template, and the helper function templates std::ref() and std::cref(). As I mentioned in my blog post on Starting Threads with Member Functions and Reference Arguments, these wrappers can be used to pass references to objects across interfaces that normally require copyable (or at least movable) objects — in that blog post, std::ref was used for passing references to objects over to the new thread, rather than copying the objects. I was recently asked what the difference was between std::ref and std::cref, and how they worked, so I thought I'd elaborate.

Deducing the Referenced Type

std::ref is a function template, so automatically deduces the type of the wrapped reference from the type of the supplied argument. This type deduction includes the const-ness of the supplied object:

int x=3;
const int y=4;
std::reference_wrapper<int> rx=std::ref(x);
// std::reference_wrapper<int> ry=std::ref(y); // error
std::reference_wrapper<const int> rcy=std::ref(y);

On the other hand, though std::cref also deduces the type of the wrapped reference from the supplied argument, it always wraps a const reference:

int x=3;
const int y=4;
// std::reference_wrapper<int> rx=std::cref(x); // error
std::reference_wrapper<const int> rcx=std::cref(x);
// std::reference_wrapper<int> ry=std::cref(y); // error
std::reference_wrapper<const int> rcy=std::cref(y);

Since a no-const-reference can always be bound to a const reference, you can thus use std::ref in pretty much every case where you would use std::cref, and your code would work the same. Which begs the question: why would you ever choose to use std::cref?

Using std::cref to prevent modification

The primary reason for choosing std::cref is because you want to guarantee that the source object is not modified through that reference. This can be important when writing multithreaded code — if a thread should not be modifying some data then it can be worth enforcing this by passing a const reference rather than a mutable reference.

void foo(int&); // mutable reference

int x=42; // Should not be modified by thread
std::thread t(foo,std::cref(x)); // will fail to compile

This can be important where there are overloads of a function such that one takes a const reference, and the other a non-const reference: if we don't want the object modified then it is important that the overload taking a const reference is chosen.

struct Foo
{
    void operator()(int&) const;
    void operator()(int const&) const;
};

int x=42;
std::thread(Foo(),std::cref(x)); // force const int& overload 

References to temporaries

std::cref has another property missing from std::ref — it can bind to temporaries, since temporary objects can bind to const references. I'm not sure this is a good thing, especially when dealing with multiple threads, as the referenced temporary is likely to have been destroyed before the thread has even started. This is therefore something to watch out for:

void bar(int const&);

std::thread t(bar,std::cref(42)); // oops, ref to temporary

Documentation

Finally, std::cref serves a documentation purpose, even where std::ref would suffice — it declares in big bold letters that this reference cannot be used to modify the referenced object, which thus makes it easier to reason about the code.

Recommendation

I would recommend that you use std::cref in preference to std::ref whenever you can — the benefits as documentation of intent, and avoiding accidental modification through the reference make it a clear winner in my opinion. Of course, if you do want to modify the referenced object, then you need to use std::ref, but such usage now stands out, and makes it clear that this is the intent.

You do still need to be careful to ensure that you don't try and wrap references to temporaries, particularly when applying std::cref to the result of a function call, but such uses should stand out — I expect most uses to be wrapping a reference to a named variable rather than wrapping a function result.

Posted by Anthony Williams
[/ cplusplus /] permanent link
Tags: , , ,

| Stumble It! stumbleupon logo | Submit to Reddit reddit logo | Submit to DZone dzone logo

Comment on this post

If you liked this post, why not subscribe to the RSS feed RSS feed or Follow me on Twitter? You can also subscribe to this blog by email using the form on the right.

8 Comments

Very informative blog. I like your blog because of unique content. thanks for sharing such a useful information.

by PHP Frameworks at 06:37:12 on Thursday, 22 July 2010

You might be interested to learn that the latest C++0x draft contains deleted versions of both ref and cref:

template <class T> void ref(const T&& t) = delete; template <class T> void cref(const T&& t) = delete;

This prevents ref and cref from binding to temporaries.
by Joe at 23:40:00 on Wednesday, 04 August 2010

This post includes all information that I have always required. Although on internet we find a lot of information but the practical information is limited which you have originated in this post.

<a href="http://www.online-dissertation-help.com/dissertation_proposal.htm">Dissertation proposal</a>
by online-dissertation-help at 12:53:18 on Wednesday, 15 September 2010

Very well explained tutorial.

by thomasgalvin at 07:45:33 on Friday, 24 September 2010
Nice article. Keep Sharing.
by John Blake at 12:54:41 on Tuesday, 16 November 2010

Great post..Thank you for the information you have shared..it is useful and helpful..Good job!

by Martin Broud at 11:30:48 on Tuesday, 08 March 2011
<a href="http://www.amandamall.com/shoes-accessories_c11">Shoes Categories</a> <a href="http://www.amandamall.com/sports-shoes_c727">Sports Shoes</a> <a href="http://www.amandamall.com/dress-shoes_c729">Dress Shoes</a> <a href="http://www.amandamall.com/baby-shoes_c731">Baby Shoes</a> <a href="http://www.amandamall.com/slippers_c733">Slippers</a> <a href="ttp://www.amandamall.com/sandals_c735">Sandals</a> <a href="http://www.amandamall.com/clogs_c737">Clogs</a> <a href="http://www.amandamall.com/dance-shoes_c739">Dance Shoes</a> <a href="http://www.amandamall.com/special-purpose-shoes_c741">Special Purpose Shoes</a> <a href="http://www.amandamall.com/shoe-parts-accessories_c743">Shoe Parts & Accessories</a> <a href="http://www.amandamall.com/casual-shoes_c745">Casual Shoes</a> <a href="http://www.amandamall.com/sports-entertainment_c12">Sports & Entertainment</a> <a href="http://www.amandamall.com/outdoor-sports_c726">Outdoor Sports</a> <a href="http://www.amandamall.com/golf_c728">Golf</a> <a href="http://www.amandamall.com/indoor-sports_c730">Indoor Sports</a> <a href="http://www.amandamall.com/tennis_c732">Tennis</a> <a href="http://www.amandamall.com/sport-jesseys_c734">Sport Jesseys</a> very good posting. I liked it. thanks
by Free Shipping at 13:06:39 on Monday, 18 April 2011

I wanted to thank you for this interesting I definitely loved every little bit of it. I have you bookmarked your web site to check out the latest stuff you post.

by Cheap Birkenstock Shoes at 11:23:18 on Tuesday, 16 August 2011

Add your comment

Your name:

Your URL:

Email address:

Person or spambot?

Your comment: