Respuestas:
Es seguro. Const ref prolonga la vida de temporal. El alcance será el alcance de const ref.
La vida útil de un objeto temporal puede extenderse uniéndose a una referencia de valor constante o a una referencia de valor (desde C ++ 11), consulte la inicialización de referencia para obtener más detalles.
Cada vez que una referencia está vinculada a un objeto temporal o subobjeto del mismo, la vida útil del temporal se extiende para que coincida con la vida útil de la referencia, con las siguientes excepciones :
- un enlace temporal a un valor de retorno de una función en una declaración de retorno no se extiende: se destruye inmediatamente al final de la expresión de retorno. Dicha función siempre devuelve una referencia colgante.
- un enlace temporal a un miembro de referencia en una lista de inicializador de constructor persiste solo hasta que el constructor sale, no mientras exista el objeto. (nota: dicha inicialización está mal formada a partir del DR 1696).
- existe un enlace temporal a un parámetro de referencia en una llamada de función hasta el final de la expresión completa que contiene esa llamada de función: si la función devuelve una referencia, que sobrevive a la expresión completa, se convierte en una referencia colgante.
- existe un enlace temporal a una referencia en el inicializador utilizado en una nueva expresión hasta el final de la expresión completa que contiene esa nueva expresión, no tanto como el objeto inicializado. Si el objeto inicializado sobrevive a la expresión completa, su miembro de referencia se convierte en una referencia colgante.
- existe un enlace temporal a una referencia en un elemento de referencia de un agregado inicializado utilizando la sintaxis de inicialización directa (paréntesis) en oposición a la sintaxis de inicialización de lista (llaves) hasta el final de la expresión completa que contiene el inicializador.
struct A { int&& r; }; A a1{7}; // OK, lifetime is extended A a2(7); // well-formed, but dangling reference
En general, la vida útil de un temporal no puede extenderse aún más "pasándola": una segunda referencia, inicializada a partir de la referencia a la que estaba vinculado el temporal, no afecta su vida útil.
como señaló @Konrad Rudolph (y vea el último párrafo de arriba):
"Si
c.GetSomeVariable()
devuelve una referencia a un objeto local o una referencia de que está extendiendo la vida útil de algún objeto, la extensión de la vida útil no se activa"
c.GetSomeVariable()
devuelve una referencia a un objeto local o una referencia de que está extendiendo la vida útil de algún objeto, la extensión de la vida útil no se activa.
No debería haber ningún problema aquí, gracias a la extensión de por vida . El objeto recién construido sobrevivirá hasta que la referencia salga del alcance.
Sí, esto es perfectamente seguro: el enlace a una const
referencia extiende la vida útil de lo temporal al alcance de esa referencia.
Sin embargo, tenga en cuenta que el comportamiento no es transitivo . Por ejemplo, con
const auto& cc = []{
const auto& c = SomeClass{};
return c;
}();
cc
cuelga
Esto es seguro
[class.temporary]/5
: Hay tres contextos en los que los temporales se destruyen en un punto diferente al final de la expresión completa . [..]
[class.temporary]/6
: El tercer contexto es cuando una referencia está vinculada a un objeto temporal. El objeto temporal al que está vinculada la referencia o el objeto temporal que es el objeto completo de un subobjeto al que está vinculada la referencia persiste durante toda la vida útil de la referencia si el valor gl al que está vinculada la referencia se obtuvo a través de uno de los siguientes : [muchas cosas aquí]
Es seguro en este caso específico. Sin embargo, tenga en cuenta que no todos los temporales son seguros de capturar por referencia constante ... por ejemplo
#include <stdio.h>
struct Foo {
int member;
Foo() : member(0) {
printf("Constructor\n");
}
~Foo() {
printf("Destructor\n");
}
const Foo& method() const {
return *this;
}
};
int main() {
{
const Foo& x = Foo{}; // safe
printf("here!\n");
}
{
const int& y = Foo{}.member; // safe too (special rule for this)
printf("here (2)!\n");
}
{
const Foo& z = Foo{}.method(); // NOT safe
printf("here (3)!\n");
}
return 0;
}
La referencia obtenida para z
NO es segura de usar porque la instancia temporal se destruirá al final de la expresión completa, antes de llegar a la printf
declaración. Salida es:
Constructor
here!
Destructor
Constructor
here (2)!
Destructor
Constructor
Destructor
here (3)!