Изменить на месте элементы вектора - PullRequest
0 голосов
/ 21 июня 2010

Следующее не работает должным образом (печать 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 ]

2 голосов
/ 21 июня 2010

Когда вы выполняете строку nodes.push_back(n);, вектор изменяется в размерах, делая недействительными ранее сохраненные ссылки, поскольку он копирует существующие элементы во вновь выделенный блок памяти.В вашем случае, *this внутри createChildren является такой ссылкой (asdf [0]).Изменение значения в нем больше не определяется поведением, потому что деструктор для этого объекта был выполнен (попробуйте определить ~Node() и посмотрите, когда он вызывается)

1 голос
/ 21 июня 2010

Решение в некоторой степени связано с тем, о чем говорит Адриан Риган.

Если вы вставите еще один элемент в вектор узлов в методе createChildren (), вполне вероятно, что этот векторизменить размер себя.Когда он делает это, он копирует все существующие элементы во вновь выделенное хранилище.

Итак, в первый раз, когда это происходит, копируется начальное значение узла 0 со значением 0.

Компиляторсгенерирует конструктор копирования по умолчанию, который выполняет побитовое копирование.Однако простая реализация конструктора копирования не поможет, так как вы всегда потеряете обновленное значение узла 0.

h.

0 голосов
/ 21 июня 2010

Если вы собираетесь поместить класс 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 после цикла.

...