Znalazłem bardzo dziwne zachowanie (na clang i GCC) w następującej sytuacji. Mam wektor, nodesz jednym elementem, instancją klasy Node. Następnie wywołuję funkcję, nodes[0]która dodaje nową wartość Nodedo wektora. Po dodaniu nowego węzła pola obiektu wywołującego są resetowane! Wydają się jednak wracać do normy po zakończeniu funkcji.
Uważam, że jest to minimalny, powtarzalny przykład:
#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;
}
Które wyjścia
Before, X = 3
After, X = 0
Finally, X = 3
Chociaż można oczekiwać, że X pozostanie niezmieniony przez ten proces.
Inne rzeczy, których próbowałem:
- Jeśli usunę linię, która dodaje
Nodewnętrzeset(), to za każdym razem wyprowadza X = 3. - Jeśli utworzę nowy
Nodei wywołam go na tym (Node p = nodes[0]), wówczas wynikiem będzie 3, 3, 3 - Jeśli utworzę odwołanie
Nodei wywołam go na tym (Node &p = nodes[0]), wówczas wynikiem będzie 3, 0, 0 (być może jest to spowodowane tym, że odwołanie zostało utracone, gdy wektor zmienia rozmiar?)
Czy z jakiegoś powodu jest to niezdefiniowane zachowanie? Dlaczego?
reserve(2)wektor przed wywołaniem,set()byłoby to zdefiniowane zachowanie. Ale napisanie takiej funkcjisetwymaga od użytkownika odpowiedniegoreserverozmiaru przed wywołaniem jej, aby uniknąć nieokreślonego zachowania jest złym projektem, więc nie rób tego.