Eu encontrei um comportamento muito estranho (no clang e no GCC) na seguinte situação. Eu tenho um vetor, nodescom um elemento, uma instância de classe Node. Então, chamo uma função nodes[0]que adiciona um novo Nodeao vetor. Quando o novo Nó é adicionado, os campos do objeto de chamada são redefinidos! No entanto, eles parecem voltar ao normal novamente quando a função é concluída.
Eu acredito que este é um exemplo reprodutível 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;
}
Quais saídas
Before, X = 3
After, X = 0
Finally, X = 3
Embora você espere que o X permaneça inalterado pelo processo.
Outras coisas que eu tentei:
- Se eu remover a linha que adiciona um
Nodeinteriorset(), ela gera X = 3 sempre. - Se eu criar um novo
Nodee chamar assim (Node p = nodes[0]), a saída será 3, 3, 3 - Se eu criar uma referência
Nodee chamar isso de (Node &p = nodes[0]), então a saída será 3, 0, 0 (talvez essa seja porque a referência é perdida quando o vetor é redimensionado?)
Esse comportamento é indefinido por algum motivo? Por quê?
reserve(2)o vetor antes de chamarset()isso, seria um comportamento definido. Mas escrever uma função comosetessa requer que o usuário tenhareservetamanho suficiente antes de chamá-la, a fim de evitar um comportamento indefinido é um design ruim, portanto, não faça isso.