다음 상황에서 매우 이상한 동작 (clang 및 GCC에서)이 발견되었습니다. nodes
하나의 요소가있는 class의 인스턴스 가있는 벡터가 있습니다 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
inside 추가하는 줄을 제거하면set()
매번 X = 3이 출력됩니다.- 새로운 것을 만들고
Node
그것을 호출하면 (Node p = nodes[0]
) 출력은 3, 3, 3입니다. - 참조를 만들고
Node
그 (Node &p = nodes[0]
) 에서 호출 하면 출력은 3, 0, 0입니다 (아마도 이것은 벡터 크기를 조정할 때 참조가 손실 되었기 때문일까요?)
어떤 이유로이 정의되지 않은 동작입니까? 왜?
reserve(2)
호출하기 전에 벡터에set()
이 동작을 정의 할 수있다. 그러나 이와 같은 함수를 작성 하려면 정의되지 않은 동작을 피하기 위해 호출하기 전에set
사용자가 적절한reserve
크기 로 적절한 크기를 요구하는 것은 나쁜 설계이므로 수행하지 마십시오.