2012-02-02 13 views
17

Esta mañana estaba trabajando en un código de plantilla donde usé un BOOST_STATIC_ASSERT para asegurarme de que no estaba creando una referencia al tipo incorrecto, ya que pensé que podría ser un mensaje de error más claro. Sin embargo, cuando he intentado quitar la aserción estática para echar un vistazo en el error del compilador alternativa que se sorprendió al descubrir que gcc ni siquiera se quejan cuando intenta hacer una const doble & refiriéndose a un int:¿Cómo maneja C++ un const double y eso se refiere a un int?

#include <iostream> 

int main() 
{ 
    int x = 5; 
    const double& y = x; 
    std::cout << y << std::endl; 

    return 0; 
} 

Compila, y ni siquiera avisa:

$ g++ ~/stuff/badRef.cpp -Wall -Wextra -pedantic 
$ a.out 
5 

¿Qué está pasando aquí? ¿Es este comportamiento indefinido? Si es así, ¿por qué no se queja gcc? En mi máquina, int es 4 bytes y el doble es 8. Esto significa que al imprimir un doble &, debe interpretar 8 bytes en esa dirección como un doble e imprimirlo, aunque en realidad hay un int 4 bytes en esa ubicación.

Muy confundido. ¡Ayuda!

+0

¿Qué versión de GCC? –

+0

Es la versión 4.3.3. – voltrevo

+0

¿Qué sucede cuando agrega 'x = 42;' después de 'const double & y = x;'? Puede ser curioso/inesperado a primera vista. – moala

Respuesta

22

const double& y = x; crea un double temporal con el valor static_cast<double>(x), luego vincula ese temporal a y. La vida útil del temporal se amplía para que coincida con la duración de y.

Esto es completamente legal C++ (03 y 11), de ahí la falta de advertencia/error.

+0

Impresionante. De hecho, lo descubrí justo antes de su respuesta mirando lo que sucede cuando incrementa x, luego imprimo y. No cambió, así que pensé - "¡por supuesto! ¡Se une a un temporal!". Además, gcc lo acepta con -std = C++ 98 también, ¿así que supongo que también es válido C++ 98? – voltrevo

+0

@ Mozza314: "* ¿Supongo que también es válido C++ 98? *" Sí; No tengo a mano una copia de ese estándar en particular, pero estoy bastante seguro de que esa no es una de las cosas que se agregaron en C++ 03.Sin embargo, tenga en cuenta que '-std = C++ 98' en realidad impone las reglas de C++ 03, no las reglas de C++ 98, no obstante, el nombre del argumento. – ildjarn

+0

No lo entiendo ... ¿por qué harías 'const double &' cuando se vincula a un temporal en lugar de 'const double'? – Mehrdad

2

const T& se puede unir a un temporal, por lo x se está convirtiendo a double y la copia es obligado a y. Si marca, verá que &x != &y. El motivo de este comportamiento es permitir el paso de literales a funciones que toman sus parámetros por referencia const.

+0

Bueno, no "se almacena la copia", 'y' se une al temporal que resulta de la conversión, porque es una referencia de const lvalue. –

+0

@CatPlusPlus: Reemplazó "almacenado en" con "unido a" a-bien, si no para aclarar, al menos para ser pedantemente correcto. : P –

11

está bien definido y es legal. y se refiere a un temporal. considerar también cuando se pasan parámetros:

void foo(const int& p); 
foo(3.14); 

Tenga en cuenta también que esto no es válida C++ si la referencia no está const. VS 6 entendió mal y permitió vincular una referencia mutable a una temporal. Esto se aplica solo a las referencias de const.

1

Este es un buen ejemplo para aquellos que piensan que los punteros y las referencias son las mismas.

double const*const y2 = &x; 

gives 
bad.cpp:7:30: error: cannot convert ‘int*’ to ‘const double* const’ in initialization 

La razón por la que funciona para las referencias se explica en las otras publicaciones.

Cuestiones relacionadas