struct init的c ++向量

时间:2018-03-14 03:30:51

标签: c++ pointers vector struct

我是C ++的新手,我正在尝试将struct的向量初始化为下面的代码。

struct Node{
int x;
Node *p;
int rank;
Node(int x) {
    this->p = this;
    this->x = x;

    this->rank = 0;
}
};

int main() {
   vector<Node> disjointSets;
   for (int i = 0; i < 50; i++) {
     Node a(i);
     disjointSets.push_back(a);
   }
}

在main中,我尝试每次创建一个Node a并将其推送到vector中。但我后来发现有一个问题,即a始终在完全相同的内存位置创建。因此,应该指向每个节点本身的p将指向循环之后的最后一个元素。有人可以解释为什么Node a总是在相同的内存地址创建,以及如何解决这个问题?

3 个答案:

答案 0 :(得分:1)

您有未定义的行为,因为您尚未为Node类定义自定义副本构造函数。

disjointSet.push_back(a);制作了a的副本。这是使用默认的复制构造函数,它只是完成所有成员变量的元素副本。因此,在副本中,p指向原始Node的地址,而不是其本身。但是当循环迭代结束时,Node被销毁,因此指针不再有效。它依赖于实现,但很常见的是,每次循环时,循环恰好使用相同的堆栈内存a,因此所有元素中的p指向同一个地址,不再是有效的Node

您需要定义一个复制构造函数,将p设置为副本的地址:

Node(const Node &oldnode) {
    p = this;
    x = oldnode.x;
    rank = oldnode.rank;
}

和复制赋值运算符:

Node& operator=(const Node &oldnode) {
    if (&oldnode != this) {
        x = oldnode.x;
        rank = oldnode.rank;
    }
    return *this;
}

答案 1 :(得分:0)

您没有使用堆内存。存储本地变量的地址并尝试在其他地方访问它是UB。如果我是正确的,答案为&#34;为什么&#34;循环的每次迭代采用相同的内存空间是实现定义的,在这种情况下,它重用相同的堆栈空间。

答案 2 :(得分:0)

您的节点是在堆栈上创建的。并且在构造函数内分配的地址指向堆栈。如果你希望Node是一个在移动/复制到容器时不会改变的常量地址,你需要堆分配它们并使用一个Node指针向量。例如。 vector<std::unique_ptr<Node>>