c++ - compiler - gcc ultima version
Inicialización de cero extraño con g++ (6)
Me encontré con un extraño comportamiento del siguiente código, mientras jugaba con la inicialización de ints usando g ++ 4.4.3.
int main()
{
int x(int());
int y = int();
cout << x << " " << y << endl;
}
el resultado es:
1 0
El valor de "y" es 0 como se esperaba, pero el valor de x es extrañamente "1".
En VS2008 produce el siguiente error de enlace (una declaración de función, pero sin definición):
unresolved external symbol "int __cdecl x(int (__cdecl*)(void))"
¿Alguien puede explicar este extraño comportamiento de g ++?
C ++ interpreta el primero como la declaración de una función.
Como han dicho otros, x es una declaración de función. Como no hay un insertador de ostream predefinido definido para los tipos de punteros de función, parece que g ++ usa la conversión bool implícita (utilizada para verificar si el puntero de una función es NULL) para encontrar una manera de generarla.
Visual C ++, por otro lado, se queja de que la función declarada x nunca se define, y por lo tanto no puede completar el enlace. Sospecho que g ++ en este caso es lo suficientemente inteligente como para ver que la función nunca se llama, y por lo tanto no se preocupa por el enlace.
Puede intentar agregar una definición ficticia de la función int x(int(*)()) { return 0xdeadbeef; } int x(int(*)()) { return 0xdeadbeef; } al código y ver qué hace MSVC con él entonces.
Esta
int x(int());
Es en realidad una declaración de función. La entrada es una función de la siguiente firma.
int fn(void)
El puntero de función pasado a std::cout << se convierte en un bool (1) ya que es un puntero que no es NULL.
Para complementar la respuesta de GMan here ( x es una definición de función) en cuanto a por qué el 1 .
La razón para que la salida sea 1 es que en el lugar de la llamada std::cout << x , la función decae en un puntero a la función (el lenguaje no le permite pasar funciones como argumentos a otras funciones, por lo que con matrices se realiza una conversión implícita a puntero a ). Ahora, no hay una sobrecarga de un ostream que tome un puntero de función, y el compilador intenta seleccionar una conversión a cualquiera de las sobrecargas disponibles. En ese punto, encuentra que la mejor secuencia de conversión es bool e imprime 1 (el puntero no es 0).
Puede verificar esto cambiando el comportamiento, puede usar std::cout << std::boolalpha << x , y se imprimirá true lugar de 1 . Además, es interesante notar que VS tiene razón con este, ya que la expresión std::cout << x requiere tomar la dirección de x , luego se usa la función y el programa está mal formado si no hay una definición para esa funcion Puedes verificarlo nuevamente proporcionando una definición:
int f() {}
int main() {
int x(int()); // 1
x( &f ); // 2
}
int x( int(*)() ) { // 3
std::cout << "In x" << std::endl;
}
Donde he realizado manualmente la conversión de function a pointer-to-function en la definición de x (1) y la llamada con el argumento f (2) - tenga en cuenta que la declaración en 1 y la definición en 3 son la misma firma , y que el compilador ejecutará el & in x( &f ) si no lo hace.
Simplemente añada más parens:
int main()
{
int x((int()));
int y = int();
cout << x << " " << y << endl;
}
Ahora x es un int, no una función.
int x(int()); Se analiza como declaración de función.
Declara una función llamada x , que devuelve un int y acepta un parámetro, que tiene el tipo de una función que devuelve un int y no acepta argumentos.
Esto se conoce como el análisis más molesto.