# Reference initialization

< cpp‎ | language

C++
 Language Headers Library concepts Language support library Diagnostics library Utilities library Strings library Containers library Algorithms library Iterators library Numerics library Input/output library Localizations library Regular expressions library (C++11) Atomic operations library (C++11) Thread support library (C++11) Filesystem library (C++17) Technical Specifications

Initialization
 Initializer Default initialization Value initialization Direct initialization Copy initialization List initialization Aggregate initialization Reference initialization Static initialization Zero initialization Constant initialization Dynamic non-local initialization Ordered dynamic initialization Unordered dynamic initialization Class member initialization Member initializer list in-class brace-or-equal initializer

Binds a reference to an object

## Contents

### 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) given T & fn () {  or T && fn () {  return object ; (4) Class::Class(...) : refmember( expr) {...} (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.

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

#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: buf_ref is now 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;
}