# Reference initialization

From cppreference.com
< cpp‎ | language

Binds a reference to an object

### Syntax

T `&` ref `=` object `;` T `&` ref `=` `{` arg1, arg2, ... `};` T `&` ref `(` object `)` `;` T `&` ref `{` arg1, arg2, ... `}` `;` | (1) |
T `&&` ref `=` object `;` T `&&` ref `=` `{` arg1, arg2, ... `};` T `&&` ref `(` object `)` `;` T `&&` ref `{` arg1, arg2, ... `}` `;` | (2) | (since C++11)
given R fn `(` T `&` arg `);` or R fn `(` T `&&` arg `);` fn `(` object `)` fn `(` `{` arg1, arg2, ... `}` `)` | (3) |
inside T `&` fn `()` or T `&&` fn `()` `return` object `;` | (4) |
given T `&` ref `;` or T `&&` ref `;` inside the definition of Class Class`::`Class(...) `:` ref`(` object`)` {...} | (5) |

### Explanation

A reference to `T` can be initialized with an object of type `T`, a function of type `T`, or an object implicitly convertible to `T`. Once initialized, a reference cannot be changed to refer to another object.

References are initialized in the following situations:

1) When a named lvalue reference variable is declared with an initializer
2) When a named rvalue reference variable is declared with an initializer
3) In a function call expression, when the function parameter has reference type
4) In the return statement, when the function returns a reference type
5) When a non-static data member of reference type is initialized using a member initializer

The effects of reference initialization are:

- If the initializer is a braced-init-list `{` arg1, arg2, ... `}` , rules of list initialization are followed.

- Otherwise, if the reference is an lvalue reference:

  - If object is an lvalue expression, and its type is `T` or derived from `T`, and is equally or less cv-qualified, then the reference is bound to the object identified by the lvalue or to its base class subobject.

    double d = 2.0;
    double& rd = d;        // rd refers to d
    const double& rcd = d; // rcd refers to d
    struct A {};
    struct B : A {} b;
    A& ra = b;             // ra refers to A subobject in b
    const A& rca = b;      // rca refers to A subobject in b

  - Otherwise, if the type of object is not same or derived from `T`, and object has conversion function to an lvalue whose type is either `T` or derived from `T`, equally or less cv-qualified, then the reference is bound to the object identified by the lvalue returned by the conversion function (or to its base class subobject).

    struct A {};
    struct B : A { operator int&(); };
    int& ir = B(); // ir refers to the result of B::operator int&

- Otherwise, if the reference is lvalue reference to const or rvalue reference (since C++11):

  - If object is a non-bit-field rvalue or a function lvalue, and its type is either `T` or derived from `T`, equally or less cv-qualified, then the reference is bound to the value of the initializer expression or to its base subobject (after materializing a temporary if necessary) (since C++17).

    struct A {};
    struct B : A {};
    extern B f();
    const A& rca2 = f(); // bound to the A subobject of the B rvalue.
    A&& rra = f();       // same as above

    int i2 = 42;
    int&& rri = static_cast<int&&>(i2); // bound directly to i2

  - Otherwise, if the type of object is not same or derived from `T`, and object has conversion function to a rvalue or a function lvalue whose type is either `T` or derived from `T`, equally or less cv-qualified, then the reference is bound to the result of the conversion function or to its base class subobject (after materializing a temporary if necessary) (since C++17).

    struct A {};
    struct B : A {};
    struct X { operator B(); } x;
    const A& r = x; // bound to the A subobject of the result of the conversion
    B&& rrb = x;    // bound directly to the result of the conversion

  - Otherwise, object is implicitly converted to `T`. The reference is bound to the result of the conversion (after materializing a temporary) (since C++17). If the object (or, if the conversion is done by user-defined conversion, the result of the conversion function) is of type `T` or derived from `T`, it must be equally or less cv-qualified than `T`, and, if the reference is an rvalue reference, must not be an lvalue (since C++11).

    const std::string& rs = "abc"; // rs refers to temporary copy-initialized from char array
    const double& rcd2 = 2;        // rcd2 refers to temporary with value 2.0
    int i3 = 2;
    double&& rrd3 = i3;            // rrd3 refers to temporary with value 2.0

### Lifetime of a temporary

Whenever a reference is bound to a temporary or to a subobject thereof, the lifetime of the temporary is extended to match the lifetime of the reference, with the following exceptions:

- a temporary bound to a return value of a function in a return statement is not extended: it is destroyed immediately at the end of the return expression. Such function always returns a dangling reference.

a temporary bound to a reference member in a constructor initializer list persists only until the constructor exits, not as long as the object exists. (note: such initialization is ill-formed as of DR 1696). | (until C++14)

- a temporary bound to a reference parameter in a function call exists until the end of the full expression containing that function call: if the function returns a reference, which outlives the full expression, it becomes a dangling reference.
- a temporary bound to a reference in the initializer used in a new-expression exists until the end of the full expression containing that new-expression, not as long as the initialized object. If the initialized object outlives the full expression, its reference member becomes a dangling reference.

a temporary bound to a reference in a reference element of an aggregate initialized using direct-initialization syntax (parentheses) as opposed to list-initialization syntax (braces) exists until the end of the full expression containing the initializer.
    struct A {
      int&& r;
    };
    A a1{7}; // OK, lifetime is extended
    A a2(7); // well-formed, but dangling reference
| (since C++20)

In general, the lifetime of a temporary cannot be further extended by "passing it on": a second reference, initialized from the reference to which the temporary was bound, does not affect its lifetime.

### Notes

References appear without initializers only in function parameter declaration, in function return type declaration, in the declaration of a class member, and with the `extern` specifier.

### Example

Run this code

    #include <utility>
    #include <sstream>

    struct S {
        int mi;
        const std::pair<int, int>& mp; // reference member
    };

    void foo(int) {}

    struct A {};

    struct B : A {
        int n;
        operator int&() { return n; }
    };

    B bar() { return B(); }

    //int& bad_r;      // error: no initializer
    extern int& ext_r; // OK

    int main() {
    //  Lvalues
        int n = 1;
        int& r1 = n;                    // lvalue reference to the object n
        const int& cr(n);               // reference can be more cv-qualified
        volatile int& cv{n};            // any initializer syntax can be used
        int& r2 = r1;                   // another lvalue reference to the object n
    //  int& bad = cr;                  // error: less cv-qualified
        int& r3 = const_cast<int&>(cr); // const_cast is needed

        void (&rf)(int) = foo; // lvalue reference to function
        int ar[3];
        int (&ra)[3] = ar;     // lvalue reference to array

        B b;
        A& base_ref = b;        // reference to base subobject
        int& converted_ref = b; // reference to the result of a conversion

    //  Rvalues
    //  int& bad = 1;        // error: cannot bind lvalue ref to rvalue
        const int& cref = 1; // bound to rvalue
        int&& rref = 1;      // bound to rvalue

        const A& cref2 = bar(); // reference to A subobject of B temporary
        A&& rref2 = bar();      // same

        int&& xref = static_cast<int&&>(n); // bind directly to n
    //  int&& copy_ref = n;                 // error: can't bind to an lvalue
        double&& copy_ref = n;              // bind to an rvalue temporary with value 1.0

    //  Restrictions on temporary lifetimes
        std::ostream& buf_ref = std::ostringstream() << 'a'; // the ostringstream temporary
                          // was bound to the left operand of operator<<
                          // but its lifetime ended at the semicolon
                          // so buf_ref is a dangling reference

        S a {1, {2, 3} };         // temporary pair {2, 3} bound to the reference member
                                  // a.mp and its lifetime is extended to match a
        S* p = new S{1, {2, 3} }; // temporary pair {2, 3} bound to the reference
                                  // member p->mp, but its lifetime ended at the semicolon
                                  // p->mp is a dangling reference
        delete p;
    }

### See also

- default initialization
- direct initialization
- value initialization
- copy initialization
- list initialization

Retrieved from "https://en.cppreference.com/mwiki/index.php?title=cpp/language/reference_initialization&oldid=109555"