在C/C++;,链表只有在堆栈中分配的头指针和在堆中分配的其他节点。这可能会导致内存泄漏? < > C和C++,链表指向指向其头节点的指针。但是,所有节点都是通过malloc()或new在堆上分配的。当头指针超出其作用域(例如其函数退出)时,在堆上分配的所有节点都将丢失。对吗?这是内存泄漏吗

在C/C++;,链表只有在堆栈中分配的头指针和在堆中分配的其他节点。这可能会导致内存泄漏? < > C和C++,链表指向指向其头节点的指针。但是,所有节点都是通过malloc()或new在堆上分配的。当头指针超出其作用域(例如其函数退出)时,在堆上分配的所有节点都将丢失。对吗?这是内存泄漏吗,c++,c,list,stack,heap,C++,C,List,Stack,Heap,C/C++如何处理此类问题?它会自动调用deallocator?(例如,free()或delete)?如果您不再有办法访问节点(并且它们仍在内存中),那么是的,这就是泄漏。该语言本身不以任何方式处理内存泄漏,但是现代操作系统在进程结束后进行清理,因此内存泄漏确实(最终)得到解决,但只能在进程执行结束时解决。(但是,不要依赖操作系统在您之后进行清理-作为程序员,这是一件可怕的事情。)如果您不再能够访问节点(并且节点仍在内存中),那么是的,这就是泄漏。该语言本身不以任何方式处理内存泄漏,但是现代操作

C/C++如何处理此类问题?它会自动调用deallocator?(例如,free()或delete)?

如果您不再有办法访问节点(并且它们仍在内存中),那么是的,这就是泄漏。该语言本身不以任何方式处理内存泄漏,但是现代操作系统在进程结束后进行清理,因此内存泄漏确实(最终)得到解决,但只能在进程执行结束时解决。(但是,不要依赖操作系统在您之后进行清理-作为程序员,这是一件可怕的事情。)

如果您不再能够访问节点(并且节点仍在内存中),那么是的,这就是泄漏。该语言本身不以任何方式处理内存泄漏,但是现代操作系统在进程结束后进行清理,因此内存泄漏确实(最终)得到解决,但只能在进程执行结束时解决。(但是,不要依赖操作系统在你之后进行清理——作为程序员,这是一件可怕的事情。)

处理这类事情的更好方法是使用标准容器,而不是一些简单的东西,除非你有充分的理由&知道你在做什么,以及为什么

标准:向量
标准::列表

但是要选择一个容器,重要的是要知道你在做什么,生命应该是什么

@杰克-无论你做什么,标准容器都不会神奇地为你处理手动分配的对象。这根本不可能

您必须改变解决问题的方法,将问题视为“手动分配的对象”。一旦您实现了这一飞跃,并意识到这是一种不好的方式,那么您可以在“它们是有价值的对象”或“它们将由共享对象管理”之间进行选择

EX1:使用shared_ptr保存新的对象(如果在MyNode周围复制是个坏主意[性能、拥有的资源、保留的状态]),则使用这种方法):

void MyFunction()
{
typedef boost::shared_ptr NodePtr;
std::列出我的清单;
my_list.push_back(NodePtr(新的MyNode(args…));
my_list.push_back(NodePtr(新的MyNode(args…));
...
//当此函数退出时,共享的ptr所拥有的节点
//它们本身属于std::list的堆栈实例
//将自动删除,无任何泄漏。。。
}
EX2:如果节点很便宜,可以将其视为可复制对象(值语义),则可以这样做:

void MyFunction()
{
std::vector my_列表;
my_list.push_back(MyNode(args…);
my_list.push_back(MyNode(args…);
...
//当此函数退出时,将直接支持作为副本的节点
//在矢量容器中,将自动删除,无任何泄漏。。。
}
如果您确实希望出于某种原因手动管理实例(通常您这样做是因为生命周期实际上并不与单个容器的生命周期相关联,而是存在一些不规则的生命周期,除了自定义算法之外,其他任何方法都无法将其整齐封装):

void MyFunction()
{
std::列出我的清单;
my_list.push_back(新的MyNode(args…);
my_list.push_back(新的MyNode(args…);
...
//我们必须手动取消分配节点,因为没有提供任何其他信息
//责任无处不在(我们正在手动管理)
typedef std::list::迭代器迭代器;
for(迭代器it=std::begin(我的列表),end=std::end(我的列表);it!=end;++it)
delete*it;//手动从堆中释放分配的内存
//“头”仍然会自动删除,因为它是堆栈分配的
//(列表对象)
}

处理这类事情的更好方法是使用标准容器,而不是一些简单的东西,除非你有充分的理由&知道你在做什么,以及为什么

标准:向量
标准::列表

但是要选择一个容器,重要的是要知道你在做什么,生命应该是什么

@杰克-无论你做什么,标准容器都不会神奇地为你处理手动分配的对象。这根本不可能

您必须改变解决问题的方法,将问题视为“手动分配的对象”。一旦您实现了这一飞跃,并意识到这是一种不好的方式,那么您可以在“它们是有价值的对象”或“它们将由共享对象管理”之间进行选择

EX1:使用shared_ptr保存新的对象(如果在MyNode周围复制是个坏主意[性能、拥有的资源、保留的状态]),则使用这种方法):

void MyFunction()
{
typedef boost::shared_ptr NodePtr;
std::列出我的清单;
my_list.push_back(NodePtr(新的MyNode(args…));
my_list.push_back(NodePtr(新的MyNode(args…));
...
//当此函数退出时,共享的ptr所拥有的节点
//它们本身属于std::list的堆栈实例
//将自动删除,无任何泄漏。。。
}
EX2:如果节点很便宜,可以将其视为可复制对象(值语义),则可以这样做:

void MyFunction()
{
std::vector my_列表;
my_list.push_back(MyNode(args…);
my_list.push_back(MyNode(args…);
...
//当此函数退出时,将直接支持作为副本的节点
//在矢量容器中,将自动删除,无任何泄漏。。。
}
如果您真的出于某种原因希望手动管理实例(通常您这样做是因为生命周期实际上并不与单个容器的生命周期相关联,而是有一些不规则的生命周期,不能由anythin整齐地封装)
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...
}
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)
}