Я знайшов дуже дивну поведінку (на кланг та GCC) у наступній ситуації. У мене вектор, nodesз одним елементом, екземпляр класу Node. Потім я викликаю функцію, nodes[0]яка додає нове Nodeу вектор. Коли додається новий Вузол, поля виклику об'єкта скидаються! Однак вони, здається, знову повертаються до норми, коли функція закінчена.
Я вважаю, що це мінімально відтворюваний приклад:
#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;
}
Які виходи
Before, X = 3
After, X = 0
Finally, X = 3
Хоча ви очікували, що X залишиться незмінним у процесі.
Інші речі, які я спробував:
- Якщо я видаляю рядок, який додає
Nodeвнутрішню частинуset(), то вона щоразу виводить X = 3. - Якщо я створю нову
Nodeі називаю її на що (Node p = nodes[0]), то вихід 3, 3, 3 - Якщо я створюю посилання
Nodeі називаю його на що (Node &p = nodes[0]), то вихід 3, 0, 0 (можливо, це тому, що посилання втрачається, коли розмір вектора змінюється?)
Чи є це невизначена поведінка чомусь? Чому?
reserve(2)вектор до виклику,set()це визначатиметься поведінкою. Але написання такої функціїsetвимагає від користувачаreserveдостатньо достатнього розміру, перш ніж викликати її, щоб уникнути невизначеної поведінки - це поганий дизайн, тому не робіть цього.