El otro día estaba programando un cierto código con árboles y cuando compilaba el programa se comportaba de forma que no conseguía entender. Para no poner el código original, he simplificado el código lo máximo posible para que se vea el comportamiento con el código tan corto y simple como sea posible.
Ante todo, para no ir repitiéndome, comento que la entrada (vía stdin) que utilizo en los códigos que voy a poner es la string 110.
El primer código es el siguiente, que se comporta como yo esperaría:
Código
#include <iostream> #include <vector> using namespace std; typedef long long ll; typedef vector<int> VI; VI fe; int llegeix() { char c; cin >> c; if (c == '0') return -1; int u = fe.size(); fe.push_back(42); int aux = llegeix(); fe[u] = aux; return u; } int main() { llegeix(); for (int i = 0; i < fe.size(); ++i) cerr << fe[i] << endl; }
La función llegeix (que para que tenga sentido, significa lee en catalán), simplemente guarda en el vector fe la posición del siguiente 1 leído o -1 si se lee un cero (caso en el que para).
Naturalmente, el programa imprime lo siguiente, que es correcto.
Código:
1
-1
Y aquí viene el juego de manos que convierte este código en la versión que manifiesta el comportamiento que no entiendo. Simplemente comento la línea 18 y asigno directamente al vector lo que devuelve la función:
Código
#include <iostream> #include <vector> using namespace std; typedef long long ll; typedef vector<int> VI; VI fe; int llegeix() { char c; cin >> c; if (c == '0') return -1; int u = fe.size(); fe.push_back(42); //int aux = llegeix(); fe[u] = llegeix(); return u; } int main() { llegeix(); for (int i = 0; i < fe.size(); ++i) cerr << fe[i] << endl; }
En mi ordenador, con esta versión de g++:
Código:
alex@portatil:~$ g++ --version
g++ (Debian 4.7.2-5) 4.7.2
Copyright (C) 2012 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Da la siguiente salida, diferente del código anterior, por motivos que no entiendo:
Código:
42
-1
He comprobado el código en IdeOne con la versión 4.8.1 que tienen actualmente y ambos códigos me dan los mismos resultados que en mi ordenador. A mi entender, dichos códigos deberían comportarse de la misma forma, ya que si bien la función recursiva modifica el vector (añade un elemento), la variable u no se ve modificada y es diferente en cada llamada de la función.
Para colmo, un amigo con Windows y Dev-C++, que creo que lleva una versión bastante antigua de g++, me dijo que al compilarlos ambos códigos daban la salida que me da a mí el primer código, es decir, la correcta.
Sinceramente no entiendo por qué ambos códigos dan resultados distintos y lo más curioso es que si el 42 que he puesto por poner algo se cambia por cualquier otro número en el segundo código, la salida del primer elemento del vector será dicho número, como si la asignación del primer elemento no se hiciera nunca.
¿Alguien puede decirme el motivo de este comportamiento?
Muchas gracias