2010-02-23 26 views
9

¿Alguien puede explicarme por qué hay una diferencia entre estas dos afirmaciones?Inicialización de referencia en C++

class A{}; 

const A& a = A();   // correct 

A& b = A();    // wrong 

Dice inicialización no válido de referencia no const de tipo A& de un temporal del tipo A

¿Por qué const importa aquí?

Respuesta

14

Las referencias no const deben inicializarse con l-values. Si pudiera inicializarlos con provisionales, ¿qué haría lo siguiente?

int& foo = 5; 
foo = 6; // ?! 

const referencias tienen la propiedad especial que se extienden la vida del árbitro, y puesto que son const, no hay ninguna posibilidad de que se le intenta modificar algo que no se sienta en la memoria. Por ejemplo:

const int& foo = 5; 
foo = 6; // not allowed, because foo is const. 

Recuerde que las referencias en realidad tienen que referirse a algo, no solo a variables temporales. Por ejemplo, el siguiente es válido:

int foo = 5; 
int& bar = foo; 
bar = 6; 
assert(foo == 6); 
+1

Espera, ¿eso significa que puedo usar 'const classA & ref = ReturnsClassAByValue();'? Pensé que la temperatura moriría en la siguiente línea. – Lucas

+2

Sí, podría usar eso. El temporal durará tanto como lo haga la variable de referencia: http://herbsutter.spaces.live.com/blog/cns!2D4327CC297151BB!378.entry –

+1

Impresionante, gracias. En SO, aprendes algo nuevo todos los días ... – Lucas

1

Para un valor temporal/r, solo puede tener una referencia constante.

Puede tener una referencia no constante a un valor no temporal/lvalue.

A a; 
A& b = a; 

Creo que la razón por qué es reforzar el hecho de que un valor de lado derecho es temporal ya que hay poco valor en ser capaz de modificar algo que va a desaparecer momentáneamente.

+1

concedido; Creo que el OP está buscando por qué ese es el caso. – fbrereto

1

En lenguaje C++, es ilegal adjuntar una referencia no constante a un valor r, mientras que está perfectamente bien adjuntar una referencia constante a un valor r. Por ejemplo, esto es legal

const int& r = 5; 

mientras que esto no es

int &r = 5; // ERROR 

un objeto temporal del tipo A devuelto por la expresión A() es un valor de lado derecho, por lo que la regla anterior se aplica en su caso también.

+0

Un valor r es un valor temporal sin nombre, como el valor de retorno de una función. – thebretness

+0

@thebretness: No necesariamente. Por ejemplo, una constante enum es un valor r, pero es * nombrado *. – AnT

3

La terminología es un poco confusa; es posible que desee investigar un poco más. Aquí está la respuesta corta:

Está asignando un objeto temporal (el resultado de llamar al constructor de la clase) a una variable. Un objeto temporal es un valor R. No puede asignar un valor R a una referencia no constante.

Puede asignar un valor R a una referencia constante, aunque la razón para permitirlo es bastante oscura.

0

Debido a que la norma dice así:

§8.5.3.5 ... De lo contrario, la referencia será una referencia lvalue a un tipo const no volátil ...

Sin embargo, si quieres mucho, lo puede conseguir:

#include <iostream> 
int main() 
{ 
    const int & cr=5; 
    int & r=const_cast<int &>(cr); 
    r=6; 
    std::cout<<r; 
} 
// outputs 6 with c++/clang++, Debian 8, amd64 

pero tenga en cuenta que la supuesta cr constante no se const más, también, y de incurrir en un comportamiento indefinido. (§1.9 (4))

Según lo sugerido por el código anterior, no existe una razón técnica para la diferencia. Por el contrario, los diseñadores tenían pesadillas sobre lo que los usuarios harían con las referencias a los temporales de las no-const.

Cuestiones relacionadas