He encontrado un comportamiento muy extraño (en clang y GCC) en la siguiente situación. Tengo un vector, nodes
con un elemento, una instancia de clase Node
. Luego llamo a una función nodes[0]
que agrega un nuevo Node
al vector. Cuando se agrega el nuevo nodo, los campos del objeto que llama se restablecen. Sin embargo, parecen volver a la normalidad una vez que la función ha finalizado.
Creo que este es un ejemplo reproducible mínimo:
#include <iostream>
#include <vector>
using namespace std;
struct Node;
vector<Node> nodes;
struct Node{
int X;
void set(){
X = 3;
cout << "Before, X = " << X << endl;
nodes.push_back(Node());
cout << "After, X = " << X << endl;
}
};
int main() {
nodes = vector<Node>();
nodes.push_back(Node());
nodes[0].set();
cout << "Finally, X = " << nodes[0].X << endl;
}
Que salidas
Before, X = 3
After, X = 0
Finally, X = 3
Aunque esperarías que X permanezca sin cambios por el proceso.
Otras cosas que he probado:
- Si elimino la línea que agrega un
Node
interiorset()
, genera X = 3 cada vez. - Si creo un nuevo
Node
y lo llamo en ese (Node p = nodes[0]
), la salida es 3, 3, 3 - Si creo una referencia
Node
y la llamo en ese (Node &p = nodes[0]
), entonces la salida es 3, 0, 0 (¿quizás esta es porque la referencia se pierde cuando el vector cambia de tamaño?)
¿Es este comportamiento indefinido por alguna razón? ¿Por qué?
reserve(2)
al vector antes de llamarlo,set()
este sería un comportamiento definido. Pero escribir una función comoset
esa requiere que el usuarioreserve
tenga el tamaño adecuado antes de llamarla para evitar un comportamiento indefinido, es un mal diseño, así que no lo haga.