添加到std :: vector时,类字段的行为异常 [英] Weird behaviour with class fields when adding to a std::vector

查看:82
本文介绍了添加到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 inside set(), 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆