J'ai trouvé un comportement très étrange (sur clang et GCC) dans la situation suivante. J'ai un vecteur, nodes
avec un élément, une instance de classe Node
. J'appelle ensuite une fonction nodes[0]
qui ajoute une nouvelle Node
au vecteur. Lorsque le nouveau nœud est ajouté, les champs de l'objet appelant sont réinitialisés! Cependant, ils semblent redevenir normaux une fois la fonction terminée.
Je pense que c'est un exemple reproductible minimal:
#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;
}
Quelles sorties
Before, X = 3
After, X = 0
Finally, X = 3
Bien que vous vous attendiez à ce que X reste inchangé par le processus.
J'ai essayé d'autres choses:
- Si je supprime la ligne qui ajoute un
Node
intérieurset()
, elle renvoie X = 3 à chaque fois. - Si je crée un nouveau
Node
et l'appelle sur ça (Node p = nodes[0]
) alors la sortie est 3, 3, 3 - Si je crée une référence
Node
et l'appelle sur ça (Node &p = nodes[0]
) alors la sortie est 3, 0, 0 (peut-être celle-ci est parce que la référence est perdue lorsque le vecteur se redimensionne?)
Ce comportement n'est-il pas défini pour une raison quelconque? Pourquoi?
reserve(2)
le vecteur avant d'appeler,set()
ce serait un comportement défini. Mais écrire une fonction commeset
celle-ci nécessite que l'utilisateur aitreserve
suffisamment de taille avant de l'appeler afin d'éviter un comportement indéfini est une mauvaise conception, alors ne le faites pas.