修改向量的元素

时间:2010-06-21 10:43:15

标签: c++ vector pass-by-reference

以下不能按预期工作(打印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;
}

3 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:1)

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

如果将另一个元素推送到“createChildren()”方法中的节点向量上,则向量需要自行调整大小。当它这样做时,它会将任何现有元素复制到新分配的存储中。

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

编译器将生成一个默认的复制构造函数,它执行按位复制。但是,实现复制构造函数不会有所帮助,因为您将始终丢失节点0的更新值。

小时。

答案 2 :(得分:0)

如果要将Node类放入向量(或任何其他容器),则需要确保它具有复制构造函数和operator = implementation,否则您应该将指针放在向量中的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.