Espacios de nombres
Variantes
Acciones

Inicialización de referencia

De cppreference.com
< cpp‎ | language

Vincula una referencia a un objeto

Contenido

[editar]Sintaxis

T&ref=objeto;

T&ref={ arg1, arg2, ...};

T&ref(objeto) ;

T&ref{ arg1, arg2, ...} ;

(1)

T&&ref=objeto;

T&&ref={ arg1, arg2, ...};

T&&ref(objeto) ;

T&&ref{arg1, arg2, ...} ;

(2) (desde C++11)
Dado Rfn(T&arg); o Rfn(T&&arg);

fn(objeto)

fn({arg1, arg2, ...} )

(3)
Dentro de T&fn() o T&&fn()

returnobjeto;

(4)
Dado T&ref; o T&&ref; dentro de la definición de Clase

Clase::Clase(...):ref(objeto) {...}

(5)

[editar]Explicación

Una referencia a T se puede inicializar con un objeto de tipo T, una función de tipo T o un objeto implícitamente convertible a T. Una vez inicializada, una referencia no se puede cambiar para hacer referencia a otro objeto.

Las referencias se inicializan en las siguientes situaciones:

1) Cuando una variable referencia lvalue denominada se declara con un inicializador.
2) Cuando una variable referencia rvalue denominada se declara con un inicializador.
3) En una expresión de llamada a función, cuando el parámetro de la función tiene un tipo referencia.
4) En la instrucción return, cuando la función devuelve un tipo referencia.
5) Cuando un dato miembro no estático de tipo referencia se inicializa usando un inicializador de miembro.

Los efectos de la inicialización de referencia son:

  • Si el inicializador es una lista de inicializadores entre llaves {arg1, arg2, ...} , se siguen las reglas de la inicialización de lista.
  • De lo contrario, si la referencia es una referencia lvalue:
  • Si objeto es una expresión lvalue, y su tipo es T o derivado de T, y es igual o menos calificado-cv, entonces la referencia se vincula al objeto identificado por el lvalue o al subobjeto de su clase base.
double d =2.0;double& rd = d;// rd se refiere a dconstdouble& rcd = d;// rcd se refiere a dstruct A {};struct B : A {} b; A& ra = b;// ra se refiere al subobjeto A en bconst A& rca = b;// rca se refiere al subobjeto A en b
  • De lo contrario, si el tipo de objeto no es el mismo o se deriva de T, y T tiene una función de conversión a un lvalue cuyo tipo es ya sea T o derivado de T, igual o menos calificado-cv, entonces la referencia se vincula al objeto identificado por el lvalue devuelto por la función de conversión (o el subobjeto de su clase base).
struct A {};struct B : A { operator int&();};int& ir = B();// ir se refiere al resultado de B::operator int&
  • De lo contrario, si la referencia es una referencia lvalue a un tipo no volátil calificado const o referencia rvalue(desde C++11):
  • Si objeto es un rvalue que no es un campo de bits o un lvalue de función, y su tipo es ya sea T o derivado de T, igual o menos calificado-cv, entonces la referencia se vincula al valor de la expresión de inicializador o a su subobjeto base (después de materializar un temporal si es necesario)(desde C++17).
struct A {};struct B : A {};extern B f();const A& rca2 = f();// vinculado al subobjeto A del rvalue B. A&& rra = f();// lo mismo que arriba   int i2 =42;int&& rri =static_cast<int&&>(i2);// vinculado directamente a i2
  • De lo contrario, si el tipo de objeto no es el mismo o derivado de T, y objeto tiene una función de conversión a un rvalue o un lvalue de función cuyo tipo es ya sea T o derivado de T, igual o menos calificado-cv, entonces la referencia se vincula al resultado de la función de conversión o al subobjeto de su clase base (después de materializar un temporal si es necesario)(desde C++17).
struct A {};struct B : A {};struct X { operator B();} x;const A& r = x;// vinculado al subobjeto A del resultado de la conversión B&& rrb = x;// vinculado directamente al resultado de la conversión
  • De lo contrario, objeto se convierte implícitamente a T. La referencia se vincula al resultado de la conversión (después de materializar un temporal)(desde C++17). Si el objeto (o si la conversión se hace mediante una conversión definida por el usuario, el resultado de la función de conversión) es de tipo T o derivado de T, debe ser igual o menos calificado-cv que T, y, si la referencia es una referencia rvalue, no debe ser un lvalue(desde C++11).
conststd::string& rs ="abc";// rs se refiere al temporal inicializado// por inicialización de copia de char arrayconstdouble& rcd2 =2;// rcd2 se refiere al temporal con value 2.0int i3 =2;double&& rrd3 = i3;// rrd3 se refiere al temporal con valor 2.0

[editar]Tiempo de vida de un temporal

Siempre que una referencia se vincula a un temporal o a un subobjeto base de un temporal, el tiempo de vida del temporal se extiende para que coincida con el tiempo de vida de la referencia, con las siguientes excepciones:

  • Un temporal vinculado a un valor de retorno de una función en una instrucción return no se extiende: se destruye inmediatamente al final de la expresión de retorno. Esta función siempre devuelve una referencia pendiente.
  • Un temporal vinculado a una referencia miembro en un constructor que usa una lista de inicializadores persiste solamente hasta que el constructor egrese, no tanto como el objeto exista (observa que tal inicialización está mal formada a partir del informe de defecto DR 1696).
(hasta C++14)
  • Un temporal vinculado a un parámetro de referencia en una llamada a función existe hasta el final de la expresión completa que contiene dicha llamada a función: si la función devuelve una referencia que vive más allá de la expresión completa, se convierte en una referencia pendiente.
  • Un temporal vinculado a una referencia en el inicializador utilizado en una expresión new existe hasta el final de la expresión completa que contiene esa expresión new, no tanto como el objeto inicializado. Si el objeto inicializado vive más allá de la expresión completa, su referencia miembro se convierte en una referencia pendiente.
(desde C++11)
  • Un temporal vinculado a una referencia en un elemento de tipo referencia de un agregado inicializado usando la sintaxis de inicialización directa (paréntesis), en lugar de la sintaxis de inicialización de lista (llaves) existe hasta el final de la expresión completa que contiene el inicializador.
struct A {int&& r;}; A a1{7};// de acuerdo, el tiempo de vida se extiende A a2(7);// bien formado, pero es una referencia pendiente
(desde C++20)

En general, el tiempo de vida de un temporal no puede extenderse "al pasarlo": una segunda referencia, inicializada a partir de la referencia a la que el temporal estaba vinculado, no afecta el tiempo de vida del temporal.

[editar]Notas

Las referencias aparecen sin inicializadores solamente en la declaración de parámetros de función, en la declaración del tipo de retorno de función, en la declaración de un miembro de clase, y con el especificador extern.

[editar]Ejemplo

#include <utility>#include <sstream>struct S {int mi;conststd::pair<int,int>& mp;// referencia miembro};   void foo(int){}   struct A {};struct B : A {int n; operator int&(){return n;};};   B bar(){return B();}   //int& bad_r; // ERROR: no hay inicializadorexternint& ext_r;// de acuerdo   int main(){// lvaluesint n =1;int& r1 = n;// referencia lvalue al objeto nconstint& cr(n);// la referencia puede ser más calificada-cvvolatileint& cv{n};// puede usarse cualquier sintaxis de inicializadorint& r2 = r1;// otra referencia lvalue al objeto n// int& bad = cr; // ERROR: menos calificada-cvint& r3 =const_cast<int&>(cr);// se necesita const_cast   void(&rf)(int)= foo;// referencia lvalue a funciónint ar[3];int(&ra)[3]= ar;// referencia lvalue a array   B b; A& base_ref = b;// referencia a subobjeto baseint& converted_ref = b;// referencia al resultado de una conversión   // rvalues// int& bad = 1; // ERROR: no se puede vincular ref lvalue a rvalueconstint& cref =1;// vinculado a rvalueint&& rref =1;// vinculado rvalue   const A& cref2 = bar();// referencia a subobjeto A del temporal B A&& rref2 = bar();// lo mismo   int&& xref =static_cast<int&&>(n);// vincular directamente a n// int&& copy_ref = n; // ERROR: no se puede vincular a un lvaluedouble&& copy_ref = n;// vincular a un rvalue temporal con valor 1.0   // restrictions on temporary lifetimesstd::ostream& buf_ref =std::ostringstream()<<'a';// el temporal ostringstream// se vinculó al operando al operando izquierdo de operator<<,// pero su duración terminó en el punto y coma:// buf_ref ahora es una referencia pendiente.   S a {1, {2,3}};// par temporal {2,3} vinculado a la referencia miembro// a.mp y su duración se extendieron para coincidir con un S* p = new S{1, {2,3}};// par temporal {2,3} vinculado a la referencia// miembro a.mp, pero su duración terminó en el punto y coma// p->mp es una referencia pendiente delete p;}


[editar]Véase también

close