[英]Allocate vector of list of structs
我有一個類,其成員是結構列表的向量,我想動態分配列表和列表中的元素。 我不確定為什么,但由於某種原因我的列表似乎是空的,即使我正在添加元素。
這是代碼:
#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();
}
打印這個:
Node 0. Edges:
Node 1. Edges:
Node 2. Edges:
好像列表是空的。 試圖使用調試來找出錯誤但沒有運氣。 我來自ANSI C背景,我仍然不確定新關鍵字的工作原理。 我應該在向量中存儲指向列表的指針嗎? 我應該在列表中存儲指向我的結構的指針嗎?
另外,如果答案也可以提供如何在類的析構函數上釋放內存,我將非常感激。
注意:模板是這樣的,我的Graph上的權重可以定義為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
上的resize(...)
方法(左側作為練習):
Graph(int numberOfNodes) {
int i;
for (i=0; i < numberOfNodes; ++i) {
nodes.push_back(list<Edge>());
}
}
還有其他一些我會采取不同的做法,但您可能希望將其帶到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
}
}
這解決了內存泄漏問題#1。
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);
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;
});
}
這應該可以修復你的輸出。
您還在操作列表的副本而不是實際列表:
list<Edge> edgesA= nodes.at(nodeA);
你應該聲明為:
list<Edge>& edgesA= nodes.at(nodeA);
// ^^ This makes it a reference instead of a copy
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.