Fundamentals 5 min read

Understanding && in C++: Rvalue References, Forwarding References, and Their Use as Function Parameters

The article explains the different meanings of the && operator in C++—as a true rvalue reference in non‑template functions, as a forwarding (universal) reference in templates, and its behavior when binding to function return values—illustrated with code examples and practical guidelines.

IT Services Circle
IT Services Circle
IT Services Circle
Understanding && in C++: Rvalue References, Forwarding References, and Their Use as Function Parameters

C++11 introduced many new language features, among which the && operator often confuses beginners because it does not always denote an rvalue reference.

Scott Meyers famously noted that "T&& doesn't always mean 'rvalue reference'".

&& as a Function Parameter

In non‑template functions, && always represents an rvalue reference, so the function can only accept rvalue arguments.

class A {<br/>    ...<br/>};<br/>void foo(A&& a) {<br/>    ...<br/>}<br/>

The foo function can be called with rvalues such as:

foo(A{});<br/><br/>A a;<br/>foo(std::move(a));<br/><br/>A get_a() {<br/>    A a;<br/>    ...<br/>    return a;<br/>}<br/>foo(get_a());<br/>

Calling it with an lvalue reference fails to compile:

A a1;<br/>    A& ar = a1;<br/>    foo(ar); // ERROR<br/>

In template functions, however, && does not necessarily mean an rvalue reference. When used as T&& in a deduced context, it is a forwarding reference (also called a universal reference), which can bind to both lvalues and rvalues.

template <typename T>
void bar(T&& t) {
    ...
}

Consequently, bar can accept a wide variety of arguments:

bar(A{});
    A a;
    bar(std::move(a));
    bar(get_a());

    A a1;
    A& ar1 = a1;
    bar(ar1);

    const A& ar2 = a1;
    bar(ar2);

Not all && in templates are forwarding references. For example, a parameter of type vector<T>&& can only bind to rvalues:

template<typename T>
void bar(vector<T>&& tv) {
    ...
}

Similarly, adding const to a deduced && makes it a true rvalue reference:

template<typename T>
void bar(const T&& v) {
    ...
}

&& When Receiving Return Values

The confusion also appears when binding the result of a function call. Declaring a variable as A&& a = test1(); makes a an rvalue reference, while using auto&& a = test2(); creates a forwarding reference that can bind to any value category.

class A {<br/>    ...<br/>};<br/>A&& a = test1(); // rvalue reference<br/>auto&& a = test2(); // forwarding (universal) reference<br/>

If the type is explicitly specified (e.g., A&&), it remains an rvalue reference and can only accept rvalues.

Understanding these distinctions helps avoid compilation errors and makes advanced C++ idioms like perfect forwarding clearer.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

templateC++move semanticsFunction Parametersforwarding referencervalue reference
IT Services Circle
Written by

IT Services Circle

Delivering cutting-edge internet insights and practical learning resources. We're a passionate and principled IT media platform.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.