Forwarding references in C++

In C++, there are different ways to pass a value to a function. Typically, at any given time, an object in C++ ‘belongs’ to a single function. The various ways to call a function differ in who owns the object, the caller or the callee (the function being called).

The simplest one is that we pass by value. In such cases, a copy is typically made of the object and both the caller and the callee own a copy.

void value(MyClass obj) {}

We can pass by reference. You recognize a reference by the single ampersand (&). The caller owns the object, but the callee gets access to it.

void reference(MyClass& obj) {}

You can also pass by an “rvalue reference” which you recognize by the ‘&&’ symbols. In such cases while the caller initially creates the object, but its ownership is passed to the callee. I personally dislike the expression ‘rvalue reference’ and I would have preferred something less technical.

void rvalue_reference(MyClass&& obj) {}

However, in some instances, you do not care whether your function gets to own the value, or has merely a reference to it. Writing two functions duplicates the code. Instead, you can then use a forwarding reference:

template <typename T>
void forwarding_reference(T&& obj) {}

It looks like an rvalue reference, but it is not: it can be either a normal reference or an rvalue reference depending on how you call it.

Here is how you might call these functions in practice:

MyClass obj;

The following table is a summary. A forwarding reference might be either a regular reference or an rvalue reference depending on how it is called.

caller owns? callee owns?
by value yes yes
by reference (&) yes no
by rvalue reference (&&) no yes

Daniel Lemire, "Forwarding references in C++," in Daniel Lemire's blog, May 13, 2024.

Published by

Daniel Lemire

A computer science professor at the University of Quebec (TELUQ).

Leave a Reply

Your email address will not be published.

You may subscribe to this blog by email.