就地修改向量的元素

发布于 2024-09-06 14:06:37 字数 801 浏览 6 评论 0原文

以下内容无法按预期工作(打印 2),因为我猜,即使向量是按引用传递的,节点也是按值传递的。我该如何解决它?

#include <iostream>
using std::cout;
using std::endl;

#include <vector>
using std::vector;

class Node{
    public:
        int value;
        Node(int);
        void createChildren(vector<Node> &);

};

//! constructor of a single node
Node::Node(int value)
{
    this->value = value;
}

void Node::createChildren(vector<Node> &nodes)
{
    for (int i = 0; i < 5; i++) {
        Node n(0);
        nodes.push_back(n);
        if (i == 0) {
            value = nodes.size();
        }
    }
}

int main(void) {
    Node a(0);
    vector<Node> asdf;
    asdf.push_back(a);
    asdf[0].createChildren(asdf);
    cout << asdf[0].value << endl;

    return 0;
}

The following doesn't work as desired (print 2) because, I guess, the nodes are passed by value even though the vector is passed by reference. How could I fix it?

#include <iostream>
using std::cout;
using std::endl;

#include <vector>
using std::vector;

class Node{
    public:
        int value;
        Node(int);
        void createChildren(vector<Node> &);

};

//! constructor of a single node
Node::Node(int value)
{
    this->value = value;
}

void Node::createChildren(vector<Node> &nodes)
{
    for (int i = 0; i < 5; i++) {
        Node n(0);
        nodes.push_back(n);
        if (i == 0) {
            value = nodes.size();
        }
    }
}

int main(void) {
    Node a(0);
    vector<Node> asdf;
    asdf.push_back(a);
    asdf[0].createChildren(asdf);
    cout << asdf[0].value << endl;

    return 0;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

居里长安 2024-09-13 14:06:37

当您执行nodes.push_back(n);行时,向量将被调整大小,在将现有成员复制到新分配的内存块时使先前保留的引用无效。在您的情况下,createChildren 内的*this 就是这样的引用(对asdf[0])。更改其中的值不再是已定义的行为,因为该对象的析构函数已执行(尝试定义 ~Node() 并查看何时调用它)

When you execute the line nodes.push_back(n);, the vector is resized, invalidating previously held references as it copies the existing members to a newly allocated memory block. In your case, *this inside createChildren is such a reference (to asdf[0]). Changing value in it is no longer defined behavior because the destructor for this object has been executed (try defining ~Node() and see when it is called)

心是晴朗的。 2024-09-13 14:06:37

该解决方案与 Adrian Regan 所说的有些相关。

如果您在“createChildren()”方法中将另一个元素推送到节点向量上,则向量很可能需要调整自身大小。当它执行此操作时,它将所有现有元素复制到新分配的存储中。

因此,第一次发生这种情况时,它会将节点 0 的初始值复制为 0。

编译器将生成一个默认的复制构造函数,该构造函数执行按位复制。然而,仅仅实现一个复制构造函数并没有什么帮助,因为你总是会丢失节点 0.h 的更新值

The solution is somewhat related to what Adrian Regan sais.

If you push another element onto the vector-of-nodes in the "createChildren()" method, there's a fair chance that the vector needs to resize itself. When it does that it copies any existing elements over to the newly allocated storage.

So, the first time this happens it is copying the inital value of node 0 with value 0.

The compiler will generate a default copy constructor which does a bitwise copy. However, just implementing a copy constructor is not going to help since you will always lose the updated value of node 0.

h.

微凉徒眸意 2024-09-13 14:06:37

如果要将 Node 类放入向量(或任何其他容器)中,则需要确保它具有复制构造函数和运算符= 实现,否则应将指向 Node 的指针放入向量

class Node {
   ...
   public:
      Node(const Node& rhs) { ... }

      Node& operator=(const Node& rhs) {
           if(this == &rhs)
              return *this;
           value = rhs.value;
           // ... other members copied ...
           return *this;
      }

      Node& operator=(Node& rhs) { ... non const version ... }
 };

之外您的 createChildren() 方法应在循环后将该值设置为 5。

If you are going to put the Node class into a vector (or any other container for that matter) you need to ensure that it has a copy constructor and and operator= implementation, otherwise you should put pointers to Node in the vector

class Node {
   ...
   public:
      Node(const Node& rhs) { ... }

      Node& operator=(const Node& rhs) {
           if(this == &rhs)
              return *this;
           value = rhs.value;
           // ... other members copied ...
           return *this;
      }

      Node& operator=(Node& rhs) { ... non const version ... }
 };

Outside of this your createChildren() method should set the value to 5 after the loop.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文