std::列出元素删除后节点的内存回收

std::list node's memory recycling after element removal

本文关键字:内存 节点 删除 元素 std      更新时间:2023-10-16

我很想知道当元素从列表中删除时,STL的std::list是否实现了某种形式的节点的"内存节省/回收",以重用先前节点占用的内存,以便将来向列表中添加新元素。

。当调用std::list::pop_back()来删除链表的最后一个元素时,该节点所占用的内存是否被保存,以至于当使用push_back()将新元素添加到链表的末尾时,没有动态内存分配给新节点,而只是先前删除的节点的内存被回收?

这有点类似于std::vector,它有闲置的容量。

这是一个相当古老的问题,但当我在谷歌上寻找有关这方面的信息时,它出现了。

当一个项目从std::list中删除时,该项目的内存将被释放并销毁,除非您提供一个替代Allocator,该Allocator在被要求释放内存时做一些不同的事情。标准库容器具有非常明确的内存特征,我怀疑任何现代标准库实现都试图重用内存。操作系统可能试图提高分配和释放的效率,但默认的分配器仍然会进行系统malloc/free调用,我认为这是您试图避免的昂贵的事情。

实现这一点的通用或通用方法是编写您自己的分配器。

只是使用std::list虽然,如果你想重用内存,你可以尝试使用splice()来重新链接项目和另一个可重用项目列表。或者如果你同时添加一个项目并删除另一个项目(例如,一个缓冲区或固定大小的队列,每当一个项目被添加到前面时,项目就从后面被删除),然后将旧项目拼接到新位置并替换其内容,等等。

关于splice的更多信息:https://en.cppreference.com/w/cpp/container/list/splice

不要混淆splice()参数。(文档上写着"另一个列表";但也可能是同一个名单;注意,迭代器不会失效。)

请注意,这是自定义内存管理的边界,因此请确保您有一个清晰,定义良好的算法来执行此操作。

与c++一样,您需要注意对象/值何时被复制、分配和可能的移动。仔细阅读std::list的文档,了解它何时分配和复制数据。https://en.cppreference.com/w/cpp/container/list

下面的示例将列表中的最后一个元素重新链接到前面:

#include <list>
#include <iostream>
#include <algorithm>
int main() {
  std::list<int> l{1, 2, 3, 4};
  std::for_each(l.begin(), l.end(), [](int i){std::cout << i << ", ";});
  std::cout << "n";
  auto topos = l.begin();
  auto frompos = l.end();
  frompos--;
  l.splice(topos, l, frompos);
  std::for_each(l.begin(), l.end(), [](int i){std::cout << i << ", ";});
  std::cout << "n";
  return 0;
  }

修改上面的代码,将结构体或对象存储在构造、销毁、复制和移动时打印出来的列表中,然后尝试使用insert()emplace()remove()pop_back()等,看看会发生什么。