Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/152.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 结构列表的分配向量_C++_List_Memory Management_Vector - Fatal编程技术网

C++ 结构列表的分配向量

C++ 结构列表的分配向量,c++,list,memory-management,vector,C++,List,Memory Management,Vector,我有一个类,它有一个成员,它是结构列表的向量,我想动态分配列表和列表中的元素。我不知道为什么,但出于某种原因,我的列表似乎是空的,即使我正在添加元素 代码如下: #include <iostream> #include <vector> #include <list> using namespace std; template <class Weight> class Graph { private: struct Edge {

我有一个类,它有一个成员,它是结构列表的向量,我想动态分配列表和列表中的元素。我不知道为什么,但出于某种原因,我的列表似乎是空的,即使我正在添加元素

代码如下:

#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();
}
好像名单是空的。尝试使用已调试的查找错误,但运气不佳。我来自ANSI C的背景,我仍然不确定新关键字是如何工作的。我应该在向量中存储指向列表的指针吗?我应该在列表中存储指向结构的指针吗

另外,如果答案也能提供如何释放类析构函数上的内存,我将非常感激

注意:模板是这样的,我的图上的权重可以定义为int或float


编辑:我只想补充一点,我以前没有使用任何硬编码指针。您在这里看到的代码是我经过几个小时的反复尝试后得到的,以使其正常工作。

如评论中所述,这里的内存管理存在许多问题,但边缘列表保持为空的原因是
addEdge(…)
中的代码

如果将其更改为:

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);
}
您将摆脱其中一个内存管理问题,并且还有一个边缘列表。为清楚起见,前面的代码是制作边列表的副本,并将新边添加到副本中,而不是原始列表

我可以看到的另一个内存管理问题是在构造函数中。这是一个没有内存管理问题的音译。使用
vector
上的方法还有其他一些方法可以实现这一点,这些方法涉及的代码较少(留作练习):

图形(int numberOfNodes){
int i;
对于(i=0;i
我还可以做一些其他的事情,但您可能希望将此内容带到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
    }
}
这将修复您的输出

您也在操作列表的副本,而不是实际列表:

list<Edge> edgesA= nodes.at(nodeA);
list edgesA=nodes.at(nodeA);
您应将其声明为:

list<Edge>& edgesA= nodes.at(nodeA);
//        ^^ This makes it a reference instead of a copy
list&edgesA=nodes.at(nodeA);
//^^这使其成为参考,而不是副本

这段代码中有很多内存管理问题。首先,您的
构造函数中存在内存泄漏。没有理由使用您编写的代码在堆上分配
列表
(或
边缘
)实例。我做了更改,但它仍然没有打印任何内容。我知道内存泄漏,实际上我是按照您描述的那样做的(没有使用原始指针),但它不工作。是的,现在它工作了,谢谢。我习惯于Java,在Java中,所有不是原语的东西都是引用。我知道如何在函数声明中使用&作为“通过引用传递”,或者从值中获取指针(例如int j=5;int*I=&j;),但我从未在声明中见过它;在GeneratorDomainGraph中,我是否也应该在此处使用引用?Graph对象在堆栈中分配,然后我将其返回给main函数。GeneratorDomainGraph中的Graph对象是否被复制到main中的Graph对象中(这是一种巨大的资源浪费,因为该图形可能是巨大的)?在这种情况下,我是否应该使用new关键字在堆中分配图形?您不会(实际上也不能)从
generateRandomGraph
函数返回引用。您正在返回一个副本(很可能会被省略),该副本将存储在
main
中的
g
变量中。因此,避免重复的正确方法是将我的函数设置为:void generateRandomGraph(Graph&g,int numberOfNodes),接受对图形对象的引用并对其进行修改,对吗?
list<Edge> edgesA= nodes.at(nodeA);
Edge *edge= new Edge;
edge->node = nodeB;
edge->weight = weight;
edgesA.push_back(*edge);
                 ^^^^^ memory leak
list<Edge> edgesA= nodes.at(nodeA);
Edge edge; // no need for heap allocation!
edge.node = nodeB;
edge.weight = weight;
edgesA.push_back(edge);
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;
    });
}
list<Edge> edgesA= nodes.at(nodeA);
list<Edge>& edgesA= nodes.at(nodeA);
//        ^^ This makes it a reference instead of a copy