简体   繁体   English

C ++中的释放(指针向量数组)

[英]Deallocation in C++ (Array of Vector of Pointers)

Ok, so I am creating a Graph class, I am hoping to be able to run algorithms on and maybe add a gui to later on this summer when I have some free time. 好吧,所以我正在创建一个Graph类,我希望能够运行算法,并且可能在今年夏天有空闲时添加一个gui。 Right now I have an adjList that is implemented as an array of vectors (one for each vertex), each vector is a list of pointers representing edges going from each associated vertex to other vertices. 现在我有一个adjList,它实现为一个向量数组(每个顶点一个),每个向量是一个指针列表,表示从每个相关顶点到其他顶点的边。 It is declared as a protected member of my Graph class like so: 它被声明为我的Graph类的受保护成员,如下所示:

std::vector <Node*> *adjList;
adjList = new std::vector<Node*>[V];

I have a side question. 我有一个附带问题。 Now here I have an array (through a pointer) of vectors that hold pointers. 现在我在这里有一个包含指针的向量数组(通过指针)。 If instead this was not an array, but rather a pointer to just a single vector of node pointers then I could call the constructor like so: 如果相反,这不是一个数组,而是指向一个节点指针的单个向量的指针,那么我可以像这样调用构造函数:

adjList = new std::vector<Node*>(10);

This would allow me to specify a default size for the dynamic array in the vector, but it seems I cannot call the constructor, or at least can't get the syntax right when I have an array. 这将允许我为向量中的动态数组指定默认大小,但似乎我无法调用构造函数,或者至少在我有数组时无法正确获取语法。

Now for my main concern. 现在主要关注我。 For each of these vectors in my pointer array I add a number of node pointers to each vector using a call to the new operator in my addVertex method. 对于我的指针数组中的每个向量,我在addVertex方法中使用对new运算符的调用为每个向量添加了许多节点指针。 Now I need to make sure I handle deallocation of all this correctly. 现在我需要确保正确处理所有这些的释放。 I believe I have an understanding of how this should work in C++, but I know pointers are tricky so I wanted to get someone to take a look before I go on adding lots to this code base. 我相信我已经理解了它应该如何在C ++中运行,但是我知道指针很棘手,所以我想让别人看看我在这个代码库中添加批量之前。 I couldn't find anything with a few searches that was quite like what I have. 我找不到任何与我所拥有的搜索相似的内容。 Here is my deallocation: 这是我的释放:

for(int i =0; i < V; i++)
    for (unsigned int j = 0; j < adjList[i].size(); j++)
        delete adjList[i][j];
delete adjList;

Will this get free all of the memory. 这将释放所有的内存。 Also is there an easy way for me to verify this for sure, eg. 还有一种简单的方法让我可以肯定地验证这一点,例如。 to keep a count of how much memory has been allocated using new while I am debugging? 在我调试的时候,要记住使用new分配了多少内存?

[EDIT: Update w/ more info] [编辑:更新w / more info]

Here is a link to Google Books showing one of the algorithms I am wanting to implement given in psuedocode. 以下是Google图书的链接 ,其中显示了我想要在psuedocode中实现的算法之一。 This version of breadth-first search operates on an adjacency list, (an array of lists of pointers). 此版本的广度优先搜索在邻接列表(指针列表数组)上运行。 Pointers must be used because of the attributes that are assigned to each node using the adjacency list. 必须使用指针,因为使用邻接列表分配给每个节点的属性。

I am wanting to retain these attributes from my BFS algorithm stored to with each node after it is ran. 我希望在运行后保存存储到每个节点的BFS算法中的这些属性。 I know it is possible to do this in other ways, perhaps indexing nodes and using parallel arrays to store the attributes. 我知道可以通过其他方式执行此操作,可能是索引节点并使用并行数组来存储属性。 But I wanted to have code that worked similar to this psuedo-code (for BFS in the link). 但我希望代码与此伪代码类似(对于链接中的BFS)。

  1. Why are you using an array of vectors? 你为什么使用一组向量?
  2. Why are you maintaining a pointer to a vector? 为什么要保持指向矢量的指针?
  3. Why are you maintaining a vector of pointers? 你为什么要保持一个指针向量?

All three of those decisions cost you and directly negate the memory-managing ability of the vector class. 所有这三个决策都会花费你并直接否定向量类的内存管理能力。 A vector is not simply an array that can grow under the covers, it also manages memory for you via a pattern known as RAII . 向量不仅仅是一个可以在封面下成长的数组,它还通过称为RAII的模式为您管理内存。

When you create a vector of pointers the vector cannot clean up the memory that the pointers refer to upon destruction, so you still need to call delete on every element of the vector. 当您创建指针向量时,向量无法清除指针在销毁时引用的内存,因此您仍需要在向量的每个元素上调用delete

When you create a pointer to a vector you cannot take advantage of the fact that the vector deallocates any memory it has allocated in its destructor. 当您创建指向向量的指针时,您无法利用向量释放它在析构函数中分配的任何内存这一事实。 Thus, once again, you negate the vector's ability to manage memory for you as you must call delete on the vector in order to prevent a memory leak. 因此,再一次,你否定了向量管理内存的能力,因为你必须在向量上调用delete以防止内存泄漏。

When you maintain an array of vectors... well, you're already using vectors, why not just use a vector<vector<T>> ? 当你维护一个向量数组时......你已经在使用向量了,为什么不使用vector<vector<T>>

The vector type dynamically allocated memory for you behind the scenes specifically to avoid the sort of issues you are encountering now. 向量类型在幕后为您动态分配内存,专门用于避免您现在遇到的问题。 Sure, you can manage your own memory (you simply deallocate in the opposite order that you allocated, which you seem to grasp), but why bother when there are mechanisms in place to do it for you? 当然,你可以管理你自己的记忆(你只需按照你所分配的相反顺序解除分配,你似乎已经掌握了),但是为什么还有机制来为你做这件事呢?

I don't understand the design goal here. 我不明白这里的设计目标。 Why not simply use a vector<vector<Edge>> and rid yourself of these problems entirely? 为什么不简单地使用vector<vector<Edge>>并完全摆脱这些问题呢?

class Edge {
    // whatever
}

class Graph {
private:
    // when instances of this class go out of scope, 
    // all of the memory allocated to these vectors is deallocated for you!
    vector<vector<Edge>> vertices;  
}

If you are building a class with a lot of indexing to internal objects through pointers, one way to ensure you delete objects at memory locations only once is to keep a memory pool. 如果您正在构建有很多索引通过指针内部对象类,一种方式,以确保您的存储位置删除对象只有一次是保持一个内存池。 For example, you can have a std::vector<Node*> Graph::memPool member. 例如,您可以拥有一个std::vector<Node*> Graph::memPool成员。 When deleting the Graph , just delete everything in Graph::memPool and not the indexes in the individual node's adjList . 删除Graph ,只需删除Graph::memPool所有内容,而不删除单个节点的adjList的索引。 Whenever a new node is created, just add it to the memory pool. 无论何时创建新节点,只需将其添加到内存池即可。

In your current example, if two nodes have an edge to the same node, you may delete an invalid memory location. 在当前示例中,如果两个节点具有同一节点的边缘,则可以删除无效的内存位置。

Another alternative is to use numbered indexes instead of pointers. 另一种方法是使用编号索引而不是指针。 The graph has a master vector of nodes while the adjacency list in each node keeps vector indexes. 该图具有节点的主矢量,而每个节点中的邻接列表保持矢量索引。

class Graph
{
    std::vector<Node> all_nodes;
    ...
};

struct Node
{
    std::vector<size_t> adjList;
    SomeDataType nodeData;//e.g. node cost, weight, reward, etc
    ...
};

No explicit dellocation is necessary in this case. 在这种情况下,不需要明确的解除定位。 Similar to using pointers, removing nodes from the graph will require scanning the adjacency lists for updating of indexes. 与使用指针类似,从图中删除节点将需要扫描邻接列表以更新索引。

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

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