Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

An rvalue reference is a compound type in C++ that binds exclusively to rvalues—temporary objects, literals, or objects explicitly cast to an rvalue category (xvalues). Denoted by the double ampersand (&&) syntax, it provides a language-level mechanism to safely identify, bind to, and mutate temporary objects before their memory is reclaimed.
Type&& reference_name = rvalue_expression;

Binding Rules and Value Categories

In the C++ expression taxonomy, an rvalue reference can only bind to expressions that evaluate to an rvalue (specifically, prvalues and xvalues). It strictly prohibits binding to lvalues (named objects with a persistent memory address) unless an explicit cast is applied.
  • prvalue (Pure Rvalue): Literals or temporary objects returned by value.
  • xvalue (Expiring Value): Objects nearing the end of their lifetime, typically created via an explicit cast to an rvalue reference.
int&& r_ref1 = 42;                  // Valid: Binds to a prvalue (literal)

std::string get_string();
std::string&& r_ref2 = get_string(); // Valid: Binds to a prvalue (temporary return value)

int x = 10;
// int&& r_ref3 = x;                // Error: Cannot bind rvalue reference to an lvalue

int&& r_ref4 = static_cast<int&&>(x); // Valid: Binds to an xvalue (explicit cast)
int&& r_ref5 = std::move(x);          // Valid: std::move is a standard library cast to T&&

Overload Resolution

Rvalue references participate heavily in function overload resolution. When the compiler encounters an overloaded function, it will preferentially bind rvalue arguments to the overload taking an rvalue reference (T&&), and lvalue arguments to the overload taking an lvalue reference (T& or const T&).
void process(std::string& str);       // Overload 1: Binds to mutable lvalues
void process(const std::string& str); // Overload 2: Binds to const lvalues and rvalues (fallback)
void process(std::string&& str);      // Overload 3: Binds specifically to mutable rvalues

std::string name = "C++";
process(name);                        // Resolves to Overload 1
process(std::string("C++"));          // Resolves to Overload 3

The Lvalue-ness of Named Rvalue References

A critical mechanical rule in C++ is that if an rvalue reference has a name, the name itself is treated as an lvalue expression. The type of the variable is T&&, but its value category when evaluated in an expression is an lvalue. This prevents temporary objects from being implicitly cannibalized multiple times.
void consume(std::string&& temp_str) {
    // 'temp_str' is an lvalue here, despite its type being std::string&&.
    
    // process(temp_str);             // This would call process(std::string&)
    
    // To pass it onward as an rvalue, it must be explicitly cast again:
    process(std::move(temp_str));     // Calls process(std::string&&)
}

Disambiguation: Forwarding References

When the && syntax is applied to a deduced template type parameter or auto, it does not strictly denote an rvalue reference. Instead, it becomes a forwarding reference (sometimes called a universal reference).
template <typename T>
void deduce_type(T&& param); // T&& is a forwarding reference, not an rvalue reference

auto&& var = x;              // auto&& is a forwarding reference
Due to C++ reference collapsing rules (& & -> &, & && -> &, && & -> &, && && -> &&), a forwarding reference can collapse into either an lvalue reference or an rvalue reference depending on the value category of the argument passed to it. A true rvalue reference requires a fully specified, non-deduced type (e.g., std::string&& or int&&).
Master C++ with Deep Grasping Methodology!Learn More