添加到std :: vector时,类字段的行为异常 [英] Weird behaviour with class fields when adding to a std::vector
问题描述
在以下情况下,我发现了一些非常奇怪的行为(在clang和GCC上).我有一个向量 nodes
,其中有一个元素,是类 Node
的一个实例.然后,我在 nodes [0]
上调用一个函数,该函数将一个新的 Node
添加到向量中.添加新节点后,将重置调用对象的字段!但是,一旦功能完成,它们似乎又会恢复正常.
I have found some very weird behaviour (on clang and GCC) in the following situation. I have a vector, nodes
, with one element, an instance of class Node
.
I then call a function on nodes[0]
that adds a new Node
to the vector.
When the new Node is added, the calling object's fields are reset! However, they seem to return to normal again once the function has finished.
我相信这是一个最小的可复制示例:
I believe this is a minimal reproducible example:
#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在整个过程中保持不变.
Though you would expect X to remain unchanged by the process.
我尝试过的其他事情:
- 如果我删除在
set()
内添加Node
的行,则每次输出X = 3. - 如果我创建一个新的
Node
并在其上调用它(Node p = nodes [0]
),则输出为3、3、3 - 如果我创建一个引用
Node
并在其上调用它(Node& p = nodes [0]
),则输出为3、0、0(也许这是因为当向量调整大小时参考丢失了吗?)
- If I remove the line that adds a
Node
insideset()
, then it outputs X = 3 every time. - If I create a new
Node
and call it on that (Node p = nodes[0]
) then the output is 3, 3, 3 - If I create a reference
Node
and call it on that (Node &p = nodes[0]
) then the output is 3, 0, 0 (perhaps this one is because the reference is lost when the vector resizes?)
这种不确定的行为是出于某种原因吗?为什么?
Is this undefined behaviour for some reason? Why?
推荐答案
您的代码具有未定义的行为.在
Your code has undefined behavior. In
void set(){
X = 3;
cout << "Before, X = " << X << endl;
nodes.push_back(Node());
cout << "After, X = " << X << endl;
}
对 X
的访问实际上是 this-> X
,而 this
是指向向量成员的指针.当您执行 nodes.push_back(Node());
时,您会在向量中添加一个新元素,然后该过程将重新分配,从而使所有迭代器,指针和引用无效.向量.这意味着
The access to X
is really this->X
and this
is a pointer to the member of the vector. When you do nodes.push_back(Node());
you add a new element to the vector and that process reallocates, which invalidates all iterators, pointers and references to elements in the vector. That means
cout << "After, X = " << X << endl;
使用的 this
不再有效.
这篇关于添加到std :: vector时,类字段的行为异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!