对于 C 和 C++,链表的指针指向其头节点。但是,所有节点都是通过 malloc() 或 new 在堆上分配的。当头指针超出其范围时,例如它的功能退出,分配在堆上的所有节点都将丢失。正确的?这是内存泄漏吗?
C/C++ 是如何处理这类问题的?它自动调用解除分配器? (例如 free() 或 delete)?
最佳答案
处理这类事情的更好方法是使用标准容器,而不是一些朴素的东西,除非你有充分的理由并且知道你在做什么,以及为什么......
std::vector <
标准::列表<>
但是要选择一个容器,重要的是要知道你在做什么,生命周期应该是多少。
@Jack - 无论您做什么,标准容器都不会神奇地为您处理手动分配的对象。这根本不可能。
您必须改变解决问题的方法,将问题视为“手动分配的对象”。一旦您实现了这一飞跃,并意识到这是一条糟糕的道路,那么您可以在“它们是值对象”或“它们将由 shared_ptr 管理”之间做出选择。
EX1:使用 shared_ptr 保存新的对象(如果围绕 MyNode 复制是一个坏主意 [性能、拥有的资源、保留的状态],这是使用的方法):
void MyFunction()
{
typedef boost::shared_ptr<MyNode> NodePtr;
std::list<NodePtr> my_list;
my_list.push_back(NodePtr(new MyNode(args...)));
my_list.push_back(NodePtr(new MyNode(args...)));
...
// when this function exits, the nodes, which are owned by shared_ptr's
// which are themselves owned by a stack instance of std::list<>
// will be automatically deleted, no leaks anywhere...
}
EX2:如果您的节点很便宜,可以将其视为可复制对象(值语义),这就是您要做的:
void MyFunction()
{
std::vector<MyNode> my_list;
my_list.push_back(MyNode(args...));
my_list.push_back(MyNode(args...));
...
// when this function exits, the nodes, which are shored directly as copies
// in the vector container, will be automatically deleted, no leaks anywhere...
}
如果出于某种原因你真的更愿意手动管理实例(通常你这样做是因为生命周期并不真正依赖于单个容器的生命周期,但是有一些不规则的生命周期,除了自定义算法之外不能被任何东西整齐地封装):
void MyFunction()
{
std::list<MyNode*> my_list;
my_list.push_back(new MyNode(args...));
my_list.push_back(new MyNode(args...));
...
// we must manually deallocate the nodes because nothing else has been given
// responsibility anywhere (we're manually managing them)
typedef std::list<MyNode*>::iterator iterator;
for (iterator it = std::begin(my_list), end = std::end(my_list); it != end; ++it)
delete *it; // manually releases our allocated memory from the heap
// the "head" is still deleted automatically because it is stack allocated
// (the list object)
}
关于c++ - 在C/C++中,链表只有头指针分配在栈中,其他节点分配在堆中。这可能会导致内存泄漏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8198006/