简体   繁体   English

分配结构列表的向量

[英]Allocate vector of list of structs

I have a class that has a member which is a vector of lists of structs and I want to dynamically allocate the lists and the elements inside the lists. 我有一个类,其成员是结构列表的向量,我想动态分配列表和列表中的元素。 I'm not sure why, but for some reason my lists seem to be empty even though I'm adding the elements. 我不确定为什么,但由于某种原因我的列表似乎是空的,即使我正在添加元素。

Here is the code: 这是代码:

#include <iostream>
#include <vector>
#include <list>

using namespace std;

template <class Weight>
class Graph {
private:
    struct Edge {
        int node;
        Weight weight;
    };

    vector<list<Edge>> nodes;
public:
    Graph(int numberOfNodes) {
        int i;
        for (i=0; i < numberOfNodes; ++i) {
            nodes.push_back(*(new list<Edge>));
        }
    }

    void addEdge(int nodeA, int nodeB, Weight weight, bool bothWays= false) {
        if (bothWays) {
            addEdge(nodeB, nodeA, weight);
        }
        list<Edge> edgesA= nodes.at(nodeA);
        Edge *edge= new Edge;
        edge->node = nodeB;
        edge->weight = weight;
        edgesA.push_back(*edge);
    }


    void print() {
        unsigned int i;
        list<Edge> edges;
        for(i=0; i < nodes.size(); ++i) {
            cout << "Node " << i << ". Edges: ";
            edges= nodes.at(i);
            typename list<Edge>::iterator iterator = edges.begin();
            typename list<Edge>::iterator end = edges.end();
            for (; iterator != end; ++iterator) {
                cout << "Node " << iterator->node << ". Weight: " << iterator->weight;
            }
            cout << endl;
        }
    }
};


Graph<int> generateRandomGraph(int numberOfNodes) {
    Graph<int> g(numberOfNodes);
    int i, j, weight=22;
    for(i=0; i < numberOfNodes; ++i) {
        for(j=i; j < numberOfNodes; j++) {
            g.addEdge(i, j, weight, true);
        }
    }
    return g;
}


int main() {
    Graph<int> g= generateRandomGraph(3);
    g.print();
}

It is printing this: 打印这个:

Node 0. Edges: 
Node 1. Edges: 
Node 2. Edges: 

As if the lists were empty. 好像列表是空的。 tried to use the debugged to find out what is wrong but with no luck. 试图使用调试来找出错误但没有运气。 I come from an ANSI C background and I'm still not sure how the new keyword works. 我来自ANSI C背景,我仍然不确定新关键字的工作原理。 Should I store a pointer to the list inside my vector? 我应该在向量中存储指向列表的指针吗? Should I store a pointer to my struct inside my list? 我应该在列表中存储指向我的结构的指针吗?

Also if the answer could also provide how to deallocate the memory on the destructor of the class I would really appreciate it. 另外,如果答案也可以提供如何在类的析构函数上释放内存,我将非常感激。

Note: the template is so that the weights on my Graph can be defined as int or float. 注意:模板是这样的,我的Graph上的权重可以定义为int或float。

EDIT: I just want to add that I was not using any hard-coded pointers before. 编辑:我只想补充一点,我之前没有使用任何硬编码指针。 The code you see here is what I got after a few hours of trial and error to get it to work. 你在这里看到的代码是经过几个小时的试验和错误后得到的代码。

As noted in the comments, there are a number of issues with memory management here, but the reason the list of edges is remaining empty is the code in addEdge(...) . 正如评论中所指出的,这里存在内存管理的许多问题,但是边缘列表保持为空的原因是addEdge(...)的代码。

If you change it to this: 如果您将其更改为:

void addEdge(int nodeA, int nodeB, Weight weight, bool bothWays= false) {
    if (bothWays) {
        addEdge(nodeB, nodeA, weight);
    }
    Edge edge;
    edge.node = nodeB;
    edge.weight = weight;
    nodes.at(nodeA).push_back(edge);
}

You will get rid of one of the memory management issues, and also have a list of edges. 您将摆脱其中一个内存管理问题,并且还有一个边缘列表。 For clarity, the previous code was making a copy of the list of edges, and adding the new edge to the copy, rather than the original list. 为清楚起见,前面的代码正在复制边列表,并将新边添加到副本,而不是原始列表。

The other memory management issue that I can see is in the constructor. 我能看到的另一个内存管理问题是在构造函数中。 Here is a transliteration without the memory management problem. 这是一个没有内存管理问题的音译。 There are other ways to do this using the resize(...) method on vector that involve less code (left as an exercise): 还有其他方法可以使用涉及较少代码的vector上的resize(...)方法(左侧作为练习):

Graph(int numberOfNodes) {
    int i;
    for (i=0; i < numberOfNodes; ++i) {
        nodes.push_back(list<Edge>());
    }
}

There are a couple of other things that I would do differently, but you might want to take this to codereview.stackexchange.com for a complete review. 还有其他一些我会采取不同的做法,但您可能希望将其带到codereview.stackexchange.com进行全面审核。

Graph(int numberOfNodes) 
{
    int i;
    for (i=0; i < numberOfNodes; ++i) 
    {
        //nodes.push_back(*(new list<Edge>));
                            ^^^^^^^^^^^^^^ memory leak
       nodes.push_back(list<Edge>()); // adds an empty list to the vector
    }
}

That fixes memory leak #1. 这解决了内存泄漏问题#1。

list<Edge> edgesA= nodes.at(nodeA);
Edge *edge= new Edge;
edge->node = nodeB;
edge->weight = weight;
edgesA.push_back(*edge);
                 ^^^^^ memory leak

To fix it: 要解决这个问题:

list<Edge> edgesA= nodes.at(nodeA);
Edge edge; // no need for heap allocation!
edge.node = nodeB;
edge.weight = weight;
edgesA.push_back(edge);

iterator is a terrible name for an iterator variable name. iterator是迭代器变量名称的可怕名称。

void print() 
{
    std::for_each(nodes.begin(), nodes.end(), [](const list<Edge>& l)
    {
        std::for_each(l.begin(), l.end(), [](const Edge& e)
        {
            std::cout << "Node " << e.node << ". Weight: " << e.weight;
        });
        std::cout << std::endl;
    });
}

That should fix your output. 这应该可以修复你的输出。

You also are operating on a copy of the list instead of the actual list: 您还在操作列表的副本而不是实际列表:

list<Edge> edgesA= nodes.at(nodeA);

You should declare it as: 你应该声明为:

list<Edge>& edgesA= nodes.at(nodeA);
//        ^^ This makes it a reference instead of a copy

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM