Ho trovato un comportamento molto strano (su clang e GCC) nella seguente situazione. Ho un vettore, nodescon un elemento, un'istanza di classe Node. Quindi chiamo una funzione nodes[0]che aggiunge una nuova Nodeal 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
Nodeinternoset(), produce sempre X = 3 ogni volta. - Se ne creo uno nuovo
Nodee lo chiamo su quello (Node p = nodes[0]), l'output è 3, 3, 3 - Se creo un riferimento
Nodee 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 generesetrichiede che l'utente abbiareservedimensioni sufficienti prima di chiamarlo per evitare comportamenti indefiniti, è una cattiva progettazione, quindi non farlo.