向量 returns 负大小 c++

Vector returns negative size c++

作为练习,我想打印出一个基于 Node 对象的树数据结构。这意味着,每个对象都有一个矢量节点,它再次包含其他节点类型的对象。但是出于某种原因,当我打印出基本上只是 returns nodes.size() 的叶节点的 this->get_nr_children 时,我得到了完全随机的(负)整数实际上 return 0。更有趣的部分是:每次我编译和执行时,它都会打印出不同的整数,这些整数总是一些低负数。我不知道发生了什么!

Node.h

#include <string>
#include <vector>

using namespace std;

class Node
{
public:
    virtual ~Node();
    Node(string name = "");
    string get_name() const;
    void set_name(string& new_name);
    int get_nr_children() const;
    Node* get_child(int i) const;
    void add_child(Node child);
    void create_complete_tree(int nr_child_nodes, int tree_depth);
    void print();

private:
    string name;
    static int node_id;
    vector<Node> nodes = {};
};

Node.cpp

#include "node.h"
#include <sstream>

using namespace std;

Node::Node(string name) {
    node_id++;
    nodes = {};
    if (name == "") {
        stringstream str_sm;
        str_sm << (node_id);
        string node_id_str = str_sm.str();
        this->name = "node_" + node_id_str;
    } else {
        this->name = name;
    }
}

Node::~Node() {
    nodes.clear();
    // node_id = 0;
}

int Node::node_id = 0;

string Node::get_name() const {
    return name;
}

void Node::set_name(string& new_name) {
    this->name = new_name;
}


int Node::get_nr_children() const {
    return nodes.size();
}

Node* Node::get_child(int i) const {
    if (i >= nodes.size()) {
        return NULL;
    }
    Node node = nodes[i];
    Node *ptrNode = &node;
    return ptrNode;
}

void Node::add_child(Node child) {
    nodes.push_back(child);
}

void Node::create_complete_tree(int nr_child_nodes, int tree_depth) {
    tree_depth--;
    if (tree_depth <= 0) {
        return;
    }
    for (int i = 0; i < nr_child_nodes; i++) {
        Node* node = new Node();
        this->add_child(*node);
        node->create_complete_tree(nr_child_nodes, tree_depth);
    }
}

void Node::print() {
    cout << this->get_name() << "\n";
    cout << "I got this many children " << this->get_nr_children();
    for (int i = 0; i < this->get_nr_children(); i++) {
        cout << "\t";
        this->get_child(i)->print();
        cout << "\n";
    }
}

main.cpp

#include <iostream>
#include "node.cpp"

using namespace std;

    int main() {
        Node* root = new Node("root");
        Node* left_child = new Node("left child");
        Node* right_child = new Node("right child");

        root->add_child(*left_child);
        root->add_child(*right_child);

        root->print();

        return 0;
    }

当我执行它时,我得到:

root I got this many children 2 left child I got this many children -62802357 right child I got this many children -62802357

Process finished with exit code 0

问题出在函数 Node* Node::get_child(int i) const 上。它 return 是一个指向在函数调用结束时销毁的对象的指针。

Node* Node::get_child(int i) const {
    if (i >= nodes.size()) {
        return NULL;
    }
    Node node = nodes[i]; // <- node is a copy of nodes[i]
    Node *ptrNode = &node;
    return ptrNode;       // <- returns a pointer to node
}                         // <- local objects are destroyed, including node

您必须 return 指向向量中实际元素的指针。

Node* Node::get_child(int i) const {
    if (i >= nodes.size()) {
        return NULL;
    }
    return  &nodes[i]; // <- Returns the address of the actual node
}
Node* Node::get_child(int i) const {
    if (i >= nodes.size()) {
        return NULL;
    }
    Node node = nodes[i];
    Node *ptrNode = &node;
    return ptrNode;
}

在您上方 return 指向在 get_child(i) returned 之后销毁的本地 Node node 的指针。正确的代码如下,return 是指向向量中子项的指针。

Node* Node::get_child(int i) const {
    if (i >= nodes.size()) {
        return NULL;
    }
    return &nodes[i];
}

main 在没有指针和内存泄漏的情况下可以更容易地实现。

int main() {
    Node root("root");

    root.add_child(Node("left child"));
    root.add_child(Node("right child"));

    root.print();

    return 0;
}

你的问题源于

this->get_child(i)->print();

get_child returns 指向本地对象的指针。当函数 returns 时该对象被销毁,因此在那个 returned Node 上对 print 的调用正在与一个已经被销毁的 Node.

你需要做的是return直接指向向量元素的指针,如

Node* Node::get_child(int i) /*const*/ { // cant be const for the return
    if (i >= nodes.size()) {
        return NULL;
    }
    return &nodes[i];
}