【问题标题】:Vector returns negative size c++向量返回负大小 c++
【发布时间】:2018-10-12 16:18:49
【问题描述】:

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

节点.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 = {};
};

节点.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 我有这么多孩子 2 left child 我有这么多孩子 -62802357 对的孩子 我有这么多孩子 -62802357

进程以退出代码 0 结束

【问题讨论】:

  • 您的问题很可能是get_nr_children 返回int,因此nodes.size()size_t 转换为int,然后溢出。
  • 这不会回答您的问题,但您应该知道add_child(*node);*node副本 放在子向量中。对note 的进一步更改(例如在create_complete_tree 中)将不会反映在您添加的副本中。

标签: c++ pointers recursion tree cout


【解决方案1】:

你的问题源于

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

get_child 返回一个指向本地对象的指针。该对象在函数返回时被销毁,因此在返回的Node 上调用print 正在使用已经销毁的Node

你需要做的是直接返回一个指向向量元素的指针

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

【讨论】:

  • 这就是我最初尝试做的事情,但后来我收到了这个错误:错误:无法使用'const std::__1::__vector_base 类型的右值初始化'Node *'类型的返回对象 >::value_type *' (aka 'const Node *')
  • @TheWill 哎呀。我忘记了函数标记为const。您要么必须删除它,要么制作矢量 mutable,要么使用 const_cast 删除 nodes[i]const
【解决方案2】:
Node* Node::get_child(int i) const {
    if (i >= nodes.size()) {
        return NULL;
    }
    Node node = nodes[i];
    Node *ptrNode = &node;
    return ptrNode;
}

get_child(i) 返回后,您在上面返回一个指向已破坏本地Node node 的指针。下面是正确的代码,它返回一个指向向量中子节点的指针。

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

【讨论】:

    【解决方案3】:

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

    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
    

    您必须从向量中返回一个指向实际元素的指针。

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

    【讨论】:

      猜你喜欢
      • 2015-10-01
      • 2021-11-22
      • 1970-01-01
      • 2014-12-10
      • 2020-10-23
      • 2015-02-01
      • 1970-01-01
      • 2021-04-09
      • 2011-11-29
      相关资源
      最近更新 更多