J'ai trouvé un comportement très étrange (sur clang et GCC) dans la situation suivante. J'ai un vecteur, nodesavec un élément, une instance de classe Node. J'appelle ensuite une fonction nodes[0]qui ajoute une nouvelle Nodeau 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
Nodeintérieurset(), elle renvoie X = 3 à chaque fois. - Si je crée un nouveau
Nodeet l'appelle sur ça (Node p = nodes[0]) alors la sortie est 3, 3, 3 - Si je crée une référence
Nodeet 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 commesetcelle-ci nécessite que l'utilisateur aitreservesuffisamment de taille avant de l'appeler afin d'éviter un comportement indéfini est une mauvaise conception, alors ne le faites pas.