我遇到了一段使用new
在函数中分配动态内存的代码,然后在main函数中调用此函数。我怀疑有一些内存泄漏问题,但我不确切知道如何解决它。以下代码已简化以演示此问题:
#include <iostream>
#include <vector>
using namespace std;
// Definition for singly-linked list.
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
ListNode* createList(void);
int main(){
ListNode* my_list = createList();
//... some code
// how to delete those objects created by new?
return 0;
}
ListNode* createList(void) {
ListNode preHead(0), *p = &preHead;
vector<int> sum = {1, 2, 3, 4, 5};
for (decltype(sum.size()) i = 0; i != sum.size(); i++){
p->next = new ListNode(sum[i]);
p = p->next;
}
return preHead.next;
}
如果我理解正确,函数createList()
会创建一个包含6个ListNode对象的列表。
除了列表中的第一个对象(preHead
)之外,其他5个对象都是动态的
使用new
分配。最后,函数createList()
返回指向列表中第二个对象的指针,
这是一个指向动态内存的指针。
my_list
是指向动态内存的正常指针还是指针?我们如何确定my_list
的类型。例如,如果我编写以下代码
ListNode l1(2);ListNode* my_list = &l1;
然后my_list
将成为ListNode对象的普通指针。这两种情况之间有什么区别?
列表中的最后5个对象是使用new
创建的,如何在使用列表后在main()
中删除它们?我是否必须遍历列表并从列表末尾开始删除,直到所有动态创建的对象都被删除?
如果是这种情况,我认为这将是麻烦和不方便的。如何在仍然返回指向ListNode对象的指针的情况下改进createList()
。
答案 0 :(得分:1)
同意上述使用std :: list的建议,我想添加以下内容: Q1)你在哪里看到“普通指针”和“动态内存指针”之间的区别?指向x的指针是指向x的指针。您应该知道是否删除它。 Q2)你要么做你的建议(从最后删除)或
void clearList(ListNode* p) {
ListNode* nextP;
while (p != NULL) {
nextP = p.next;
delete p;
p = nextP;
}
}
答案 1 :(得分:1)
my_list是一个正常的指针还是指向动态内存的指针?
你的指针是一个指针,它是一个指向内存的变量,指向动态分配的内存的指针或不指向内存的指针之间确实没有区别。唯一的区别是你必须清理你拥有的动态分配的内存。(如果你动态分配它,你应该知道哪些内容)
动态内存的一个安全替代方法是使用std::shared_ptr
和std::unique_ptr
我不会在这里详细介绍,但它们可以为您节省内存管理的麻烦,所以请查阅它们。
我们如何决定my_list的类型。例如,如果我写的话 以下代码
ListNode l1(2); ListNode * my_list =&amp; l1;
这是指向堆栈上分配的内存的指针(所以不是动态的,因为你没有调用new)
列表中的最后5个对象是使用new创建的,如何删除 使用列表后,他们在main()?我是否必须遍历列表 并从列表末尾开始删除,直到创建所有对象 动态删除?
是的,如果你愿意的话,你可以循环遍历它们并以这种方式删除它们,但是你将如何进入上一个?另一种解决方案是:
ListNode* tempPtr;
while(my_list) // This works since you are initializing next to null.
{
tempPtr = my_list->next;
delete my_list;
my_list = tempPtr;
}
如果是这种情况,我认为这将是麻烦和不方便的。 如何在仍然返回的条件下改进createList() 指向ListNode对象的指针。
确实没有,如果你不在这里动态分配内存或使用静态或全局变量,它将在函数结束时消失。但是,您可以使用std::vector
或std::list
执行与当前相同的操作。