Qq0*_*Qq0 32 c++ vector push-back stdvector undefined-behavior
在以下情况下,我发现了一些非常奇怪的行为(在 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;
}
Run Code Online (Sandbox Code Playgroud)
哪些输出
#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;
}
Run Code Online (Sandbox Code Playgroud)
尽管您希望 X 在该过程中保持不变。
我尝试过的其他事情:
Nodeinside的行set(),那么它每次都会输出 X = 3 。Node并在 ( Node p = nodes[0])上调用它,那么输出是 3, 3, 3Node并在 ( Node &p = nodes[0])上调用它,那么输出为 3, 0, 0(也许这是因为当向量调整大小时引用丢失了?)出于某种原因,这是未定义的行为吗?为什么?
Nat*_*ica 39
您的代码具有未定义的行为。在
void set(){
X = 3;
cout << "Before, X = " << X << endl;
nodes.push_back(Node());
cout << "After, X = " << X << endl;
}
Run Code Online (Sandbox Code Playgroud)
该访问X是真的this->X和this是一个指针向量的成员。当你nodes.push_back(Node());向向量添加一个新元素时,该过程会重新分配,这会使向量中的所有迭代器、指针和元素引用无效。这意味着
cout << "After, X = " << X << endl;
Run Code Online (Sandbox Code Playgroud)
正在使用this不再有效的 a。
Dut*_*n18 15
nodes.push_back(Node());
Run Code Online (Sandbox Code Playgroud)
将重新分配向量,从而更改 的地址nodes[0],但this不会更新。
尝试用set以下代码替换该方法:
void set(){
X = 3;
cout << "Before, X = " << X << endl;
cout << "Before, this = " << this << endl;
cout << "Before, &nodes[0] = " << &nodes[0] << endl;
nodes.push_back(Node());
cout << "After, X = " << X << endl;
cout << "After, this = " << this << endl;
cout << "After, &nodes[0] = " << &nodes[0] << endl;
}
Run Code Online (Sandbox Code Playgroud)
请注意&nodes[0]调用后有何不同push_back。
-fsanitize=address会捕捉到这一点,甚至会告诉你内存在哪一行被释放,如果你也用-g.
| 归档时间: |
|
| 查看次数: |
1681 次 |
| 最近记录: |