Ho trovato un comportamento molto strano (su clang e GCC) nella seguente situazione. Ho un vettore, nodes
con un elemento, un'istanza di classe Node
. Quindi chiamo una funzione nodes[0]
che aggiunge una nuova Node
al vettore. Quando viene aggiunto il nuovo nodo, i campi dell'oggetto chiamante vengono resettati! Tuttavia, sembrano tornare alla normalità una volta terminata la funzione.
Credo che questo sia un esempio riproducibile minimo:
#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;
}
Quali uscite
Before, X = 3
After, X = 0
Finally, X = 3
Anche se ti aspetteresti che X rimanga invariato dal processo.
Altre cose che ho provato:
- Se rimuovo la linea che aggiunge un
Node
internoset()
, produce sempre X = 3 ogni volta. - Se ne creo uno nuovo
Node
e lo chiamo su quello (Node p = nodes[0]
), l'output è 3, 3, 3 - Se creo un riferimento
Node
e lo chiamo su quello (Node &p = nodes[0]
), l'output è 3, 0, 0 (forse questo è perché il riferimento viene perso quando il vettore viene ridimensionato?)
Questo comportamento indefinito è per qualche motivo? Perché?
reserve(2)
il vettore prima di chiamareset()
questo sarebbe definito comportamento. Ma scrivere una funzione del genereset
richiede che l'utente abbiareserve
dimensioni sufficienti prima di chiamarlo per evitare comportamenti indefiniti, è una cattiva progettazione, quindi non farlo.