Mr.*_*C64 3 c++ memory memory-management stl list
我很想知道当从列表中删除元素时, STL 是否std::list实现某种形式的节点“内存节省/回收” ,以重用先前节点占用的内存,以便将来向列表中添加新元素。
例如,当std::list::pop_back()调用删除链表的最后一个元素时,该节点占用的内存是否已保存,这样当使用将新元素添加到链表末尾时push_back(),就不会为新元素分配动态内存节点,但只是回收先前删除的节点的内存?
这有点类似于std::vector具有闲置容量的 。
这是一个很老的问题,但当我寻找这方面的信息时,它出现在谷歌上。
当从 a 中删除一个项目std::list时,该项目的内存将被释放并销毁,除非您提供一个备用分配器,该分配器在要求释放内存时执行不同的操作。标准库容器具有定义明确的内存特征,我怀疑任何现代标准库实现都会尝试重用内存。操作系统可能会尝试提高分配和释放的效率,但默认分配器仍会进行系统 malloc/free 调用,我认为这是您试图避免的昂贵的事情。
实现此目的的通用方法是编写自己的分配器。
只是使用std::list,如果您想重用内存,您可以尝试使用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;
}
Run Code Online (Sandbox Code Playgroud)
修改上面的内容,将结构体或对象存储在列表中,并在构造、销毁、复制和移动时打印出来,然后尝试使用insert()、emplace()、remove()、pop_back()等来看看会发生什么。