Double Address Operator and & in C++



&& is a new reference operator defined in the C++11 standard. int&& a means "a" is an r-value reference. && is normally only used to declare a parameter of a function. And it only takes an r-value expression.
Simply put, an r-value is a value that doesn't have a memory address. E.g., the number 6 and character 'v' are both r-values. int a, a is an l-value, however, (a+2) is an r-value.

Example

#include <iostream>
using namespace std;

void foo(int&& a)
{
    cout << "Value received: " << a << endl;
}

int main()
{
    int b = 10;

    // foo(b);       //Error: An rValue reference cannot be pointed to a lValue.
    foo(5);          //5 is an rvalue (temporary)
    foo(b + 3);      //b+3 is also an rvalue

    // int&& c = b;  //Error. An rValue reference cannot be pointed to a lValue.
    int&& d = 5;     //Compiles with no error.

    cout << "Value in d: " << d << endl;

    return 0;
}

Output

Value received: 5
Value received: 13
Value in d: 5

In C++, a single ampersand (&) declares a reference, which is used to get the memory address of a variable. Double Ampersand (&&) is used to declare an rvalue reference as discussed above, which allows you to bind to temporary (rvalue) variables.

Here we will read more about these two in detail.

C++ Single Ampersand (&)

There are three main uses of the single ampersand in C++;

Accessing Memory Address

The most common use of the & operator is to get the memory address of a variable; therefore, here it does not give the value of a variable, but provides its location in memory. This is done using a pointer.

Syntax

Here is the following syntax for this.

pointer_type *pointer_name = &variable_name;

Example

#include <iostream>
using namespace std;

int main() {
    int x = 10; 
    int *ptr = &x;      // Pointer 'ptr' stores the memory address of 'x'

    cout << "Memory address of x: " << &x << endl;  // Directly using &x to get memory address
    cout << "Pointer ptr holds the address: " << ptr << endl;  // ptr stores the memory address
    cout << "Value at the address stored in ptr: " << *ptr << endl;  // Dereferencing ptr to get value of 'x'

    return 0;
}

Output

Memory address of x: 0x7ffce192faf4
Pointer ptr holds the address: 0x7ffce192faf4
Value at the address stored in ptr: 10

Explanation

In the above example, the pointer is used to store and access the memory address of a variable using the & (address-of) and * (dereference) operators.
Here, a pointer ptr of type int* is declared and stores the memory address of the variable x using the & operator. The & operator doesn't give the value of x but provides the memory location of x.
Then dereferencing *ptr is used to access the value stored at the memory address.

Creating a Variable Reference

It is used to create a reference to a variable, where this reference is just like another name for an existing variable.

Syntax

type &reference_name = existing_variable;

Here, type is the data type of the variable (e.g., int, double, char, etc.).
& is reference operator.

Example

#include <iostream>
using namespace std;

int main() {
    int a = 10;     
    int &ref = a;  

    cout << "Original value of a: " << a << endl;  
    cout << "Reference value: " << ref << endl;    

    ref = 20;  // Changing the value of 'ref', which also changes 'a'
    cout << "New value of a: " << a << endl;      
    cout << "New value of ref: " << ref << endl; 

    return 0;
}

Output

Original value of a: 10
Reference value: 10
New value of a: 20
New value of ref: 20

Explanation

In the above code, a reference to a is declared using &, which means now ref and a both refer to the same memory location.

Therefore, whatever changes we make to the value of ref, it will also change the value of a, as they both point to the same location.

Modifying an Argument by Reference

It is also used to pass arguments by reference, which allows the function to modify the original value. Here, the function directly works with the memory location of the argument, not a copy.

Syntax

void function_name(type ¶meter) {
    // Function body
}

Example

#include <iostream>
using namespace std;

void increaseByTen(int &num) {
    num = num + 10;  // Directly modifies the original value of num
}

int main() {
    int number = 5;  
    cout << "Before: " << number << endl;  
    
    increaseByTen(number);  // Pass number by reference
    
    cout << "After: " << number << endl; 
    return 0;
}

Output

Before: 5
After: 15

Explanation

The above code shows the use of references to modify the original variable, which is passed into a function.

Here, the function takes an integer reference (int &num) as its parameter, and as num is a reference to the original variable, any modification to num will directly affect the original variable passed to it.

C++ Double Address Operator (&&)

The double address operator (&&) in C++ is used to declare an rvalue reference, which is used to bind to temporary objects.

What is rvalue?

For this, let's first understand the difference between rvalue and lvalue.
The lvalue (Left side of assignment) is the object which has a name and a memory address and can appear on the left or right of = and can bind to T&.
Example: int x = 10; Here, x is an lvalue.

The rvalue(Right side of assignment) is a temporary object/value, which does not have a name and cannot appear on the left-hand side of an assignment. This exists only during the expression and can bind to T&&.
Example: 10, x + y, 5 * 2 are rvalues.

Syntax

Here is the following syntax for it.

datatype&& reference_name = temporary_value;

Example

#include <iostream>
using namespace std;

int getValue() {
    return 42;  // Returns a temporary (rvalue)
}

int main() {
    int&& ref = getValue();  // rvalue reference to a temporary value
    cout << "Value using rvalue reference: " << ref << endl;  

    // Modifying the value
    ref = 100;
    cout << "Modified value: " << ref << endl;  

    return 0;
}

Output

Value using rvalue reference: 42
Modified value: 100

Explanation

In the above code, a function getValue() returns the integer value 42, which is an rvalue, meaning a value without any name, also known as a temporary object.
This temporary value can be treated like a regular value, but it's mostly discarded after use.

So, ref is an rvalue reference, which points to 42 and prints 42, but when assigning 100 to ref, even though ref was originally bound to a temporary value, it behaves just like a regular variable, and its value can be modified.
Therefore, in conclusion, C++ references (&) can only bind to lvalues (named variables), but temporary values like 42 are rvalues, and cannot be bound to normal references. So, C++11 introduced && to allow binding to rvalues.

Updated on: 2025-05-05T17:06:22+05:30

19K+ Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements