2011-12-22 14 views
17

Naturalmente, esto no se compilará:¿Los números literales son mutables o no?

int &z = 3; // error: invalid initialization of non-const reference .... 

y esto se compilará:

const int &z = 3; // OK 

Ahora, tenga en cuenta:

const int y = 3; 
int && yrr = y; // const error (as you would expect) 
int && yrr = move(y); // const error (as you would expect) 

Pero estas líneas siguientes no compilar para mí . Creo que no debería.

int && w = 3; 
int && yrr = move(3); 
void bar(int && x) {x = 10;} 
bar(3); 

¿No permitían esas dos últimas líneas permitir la modificación del literal 3? ¿Cuál es la diferencia entre 3 y un const int? Y finalmente, ¿hay algún peligro con la 'modificación' de los literales?

(g ++ - 4,6 (GCC) 4.6.2 con -std=gnu++0x -Wall -Wextra)

+1

Para responder a mi propia pregunta: In 'move (3)' tal vez se copia el 3 primero para crear una int temporal que se destruirá al final de la declaración. ¿Es esta la explicación? –

+0

En su segunda declaración: const &z = 3; falta el especificador de tipo. entonces no compila –

+0

Gracias, @CJohnson, normalmente copio y pego código de trabajo aquí. ¡Pero fui descuidado con ese trazador! –

Respuesta

13

La referencia rvalue al literal 3:

int && w = 3; 

es en realidad unido a un temporal que es el resultado de evaluar la expresión 3. No está obligado a algunos platónicos literal 3.

(todos los estándares siguientes referencias son a partir del proyecto de marzo de 2011, n3242) "Lvalues ​​y rvalues"

3.10/1

The value of a literal such as 12, 7.3e5, or true is also a prvalue

Luego 8.5. 3 "Referencias" da las reglas de cómo una referencia está obligado cae hasta el último caso, que dice:

Otherwise, a temporary of type “cv1 T1” is created and initialized from the initializer expression using the rules for a non-reference copy-initialization (8.5). The reference is then bound to the temporary.

y da como ejemplo algo muy cercano a lo que está en su pregunta:

double&& rrd = 2; // rrd refers to temporary with value 2.0 
+0

Gracias, pero si eso fuera cierto, ¿no debería funcionar? 'move (3) = 6;' En su lugar obtengo un error "* error: usando xvalue (referencia de valor r) como lvalue *". Es hora de que lea sobre valores x y valores pr y todo eso otra vez :-) –

+3

Gracias a su respuesta, creo que puedo responder a mi comentario de hace unos segundos. Puedo ver que 'move (3)' es un valor r (claramente, no tiene nombre). Mientras que dentro de mi función 'void bar (int && x) {x = 10;}' hay un nombre para 'x'. Esta parece ser la diferencia entre 'x = 6' y' move (3) = 6'. Ambos son '&&' pero uno es un lvalue y el otro no. Y esta distinción es lo que lleva al mensaje de error para 'mover (3) = 6'. –

+0

@ Aaron: (Un retraso) Además de su comentario: en algún lugar, el estándar especifica que un valor de r nombrado es un valor l, así que sí, así es exactamente como funciona. :) – Xeo

Cuestiones relacionadas