分配结构列表的向量
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背景,我仍然不确定新关键字的工作原理。我应该在向量中存储指向列表的指针吗?我应该在列表中存储指向结构的指针吗?
此外,如果答案还可以提供如何在类的析构函数上释放内存,我将不胜感激。
注意:模板是为了让我的图表上的权重可以定义为 int 或 float。
编辑:我只想补充一点,我以前没有使用任何硬编码指针。您在这里看到的代码是我经过几个小时的反复试验后得到的代码,以使其正常工作。
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
如注释中所述,此处的内存管理存在许多问题,但边缘列表保持为空的原因是 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 进行完整的审查。
相关文章:
- 如何在向量列表初始化时避免对象复制以及如何延长临时的生存期
- 如何在C++中声明抽象类的向量列表?
- 创建以向量/列表迭代器为键的映射
- 如何在不以不同方式创建每个向量的情况下制作 2-D 向量列表?
- 在为工作线程访问 lambda 中捕获的向量列表中的元素引用时,是否需要互斥锁?
- 根据优先级对向量列表进行字典式排序
- SIGBART 错误向量<列表<myClass>>
- C++向量列表
- 基本STL:向量列表或列表向量,在这种特殊情况下哪个会更好
- 通过 JNI 传递、返回和转换为向量列表列表
- C++:向量中向量列表的有效复制
- 从向量列表调用成员函数指针
- 多类型容器(数组/向量/列表)传统上是如何在C++实现的?(当然没有元组)
- 从向量列表c++中删除一个向量元素
- 向量列表(c++)
- 从整数向量列表中删除重复项的快速方法
- 初始化动态向量列表
- 当输出向量列表时,输出的量是平方的
- 在并行追加时,使用向量列表和向量的向量对性能的影响
- 在向量/列表中,您是否真的将其应用于对象?(C++)