当我在VS2017中运行下一个代码时:
#include <boost/pool/pool_alloc.hpp>
#include <map>
#include <iostream>
int main()
{
using Map = std::map<int, int, std::less<int>, boost::pool_allocator<std::pair<const int, int>>>;
using Pool = boost::singleton_pool<boost::pool_allocator_tag, sizeof(Map)>;
Map temp;
for (int i = 1; i < 5; i++) temp[i] = i;
std::cout << "First addresses:\n";
for (auto& kv : temp) std::cout << &kv.second << "\n";
temp.clear();
Pool::purge_memory();
Map temp2;
for (int i = 1; i < 5; i++) temp2[i] = i;
std::cout << "Second addresses:\n";
for (auto& kv : temp2) std::cout << &kv.second << "\n";
temp2.clear();
Pool::purge_memory();
return 0;
}
我得到了输出:
First addresses:
02A108F4
02A1090C
02A10924
02A1093C
Second addresses:
02A1090C
02A10924
02A1093C
02A10954
这种行为似乎不正确:地址02A108F4
发生了什么?它似乎在清除期间没有返回池中。
当我使用std::vector
而不是std::map
时,不会发生这种情况。
gcc似乎也正确地返回了内存:Live example。
这是VS2017中的错误吗?
答案 0 :(得分:2)
您正在考虑有关池的实施细节的事情。你很可能是有损失的,但你不能从你看到的分配模式中得出结论。
此外,您正在清除与sizeof(int)
关联的池分配器的内存。但是,value_type已经是std::pair<int const, int>
,这使得map实现分配了一个未指定的节点类型。
哦,你的分配器工作的原因完全一样:容器实现知道你不可能提供正确类型的分配器,因为分配的类型是未指定的。因此它始终是rebind to get the required type。
所以,至少要做到这一点
<强> Live On Rextester 强>
#include <boost/pool/pool_alloc.hpp>
#include <map>
#include <iostream>
using Map = std::map<int, int, std::less<int>, boost::pool_allocator<int>>;
using Pool = boost::singleton_pool<boost::pool_allocator_tag, sizeof(Map::value_type)>;
void foo() {
Map temp;
for (int i = 1; i < 5; i++) temp[i] = i;
std::cout << "First addresses:\n";
for (auto& kv : temp) std::cout << &kv.second << "\n";
}
int main()
{
foo();
Pool::purge_memory();
foo();
Pool::purge_memory();
}
但是,这仍然是假设实现细节。我认为 c ++ 17为您提供了更多信息(http://en.cppreference.com/w/cpp/container/node_handle)或者您可以看到Boost Container有相关详细信息:https://www.boost.org/doc/libs/1_51_0/doc/html/boost/container/map.html#id463544-bb