开发者

Modify in place the elements of a vector

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;
}


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)


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.


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜