c++ - ¿Encuadernación rvalue a referencia no const mediante puntero fundido?
reference g++ (3)
Como ha dicho templatetypedef, parece ser un error en el compilador. Cuando se compila con la versión 4.6.0 de GCC, proporciona:
error: taking address of temporary [-fpermissive]
Y, por supuesto, con la adición de -fmisivo, compila pero se queja, pero aún así no se cuelga e imprime el resultado correcto. Supongo que GCC está haciendo trampa un poco en condiciones "permisivas".
No entiendo cómo se compila / no compila el siguiente código:
struct Temp
{
int i;
};
int main(int argc, char * argv[])
{
//Temp &ref1 = (Temp){42}; // Error, as expected
Temp &ref2 = *(Temp*)&(Temp){42}; // A-OK
std::cerr << ref2.i << std::endl;
return 0;
}
Estoy usando g ++ 4.4.4.
Podría estar equivocado acerca de esto, pero esto parece un error en el compilador. El estándar ISO C ++, §5.3.1 / 2, analiza el operador &
como
El resultado del operador unario es un puntero a su operando. El operando debe ser un lvalue o un id calificado.
La sección §5.4 / 1 discute el operador de casting como
El resultado de la expresión ( cast ) de expresión es de tipo
T
El resultado es un lvalue si T es un tipo de referencia; de lo contrario , el resultado es un valor r.
Esto parece sugerir que
(Temp){42}
Produce un valor r, que no debe permitirse legalmente que tome la dirección de uso de &
.
Se me conoce que cometí errores al leer las especificaciones antes, por lo que si alguien pudiera confirmar esto sería increíble.
Tu código no es realmente C ++. Utiliza un literal compuesto que es una característica C99. En C99 evalúa a un valor l y tomar la dirección del literal está completamente bien allí. Integrando esta extensión en C ++, GCC parece cambiar su regla y convertirla en un valor r, ajustando mejor su clasificación en las reglas existentes de C ++ para los moldes habituales que también producen valores r.
A GCC no le gusta &(Temp){42}
, quejándose de que tomo la dirección de un temporal. Es una advertencia sobre el código no válido que aún acepta pero que realmente no le gusta. La misma advertencia se da para otros códigos obviamente incorrectos como &A()
, que es un lanzamiento de C ++ de estilo funcional legal, que también produce un valor r y por lo tanto no se puede usar como el operando del operador de dirección de.
La integración de literales compuestos en C ++ por GCC también destruye el temporal prematuramente, como se puede ver en la siguiente prueba
#include <iostream>
struct B {
~B() {
std::cout << "~B" << std::endl;
}
};
struct A { int i; B b; };
int main() {
A *a = &(A){0};
std::cout << "main" << std::endl;
}
En C99, el objeto al que se refiere el literal estará vivo para todo el bloque (tendrá una duración de almacenamiento automática). En GNU C ++, el objeto ya está destruido al final de la expresión completa, incluso antes de que se llegue al final de su bloque (el "~ B" se imprime antes que el "principal").