这是一个明显的例子,说明当 boost 成为 C++ 的标准部分时会发生什么。
std::unordered_map
实际上缺乏对释放内存的控制,上述答案是不正确的。
在 a发生之前, Astd::unordered_map
可能不会释放任何内存。rehash
当记录可能发生重新散列时,如果您查看size()
文档,它只是说它是元素的数量,如果您想要一个实际大小的想法,您必须在映射中添加一个自定义分配器并计算分配/释放的字节数。
很遗憾,因为没有记录该行为(也没有一些 API 来控制它),您不知道实现是否有可用内存(如果您暂时不使用地图则很好),或者是否实现缓存内存(如果您要再次插入不同的元素,那很好)。
这使得以内存有效的方式使用 unordered_map 非常困难。此外,这基本上在没有记录的情况下为巨大的内存使用留出了空间(没有任何地方说明没有元素的地图可能需要数百兆字节)
这是一个自定义分配器,用于分析内存使用情况
#include <unordered_map> //c++ container but in practice the same of boost
#include <memory>
#include <iostream>
using namespace std;
size_t counter = 0;
template <typename T>
class countingAllocator: public std::allocator<T>
{
public:
typedef size_t size_type;
typedef T* pointer;
typedef const T* const_pointer;
template<typename _Tp1>
struct rebind
{
typedef countingAllocator<_Tp1> other;
};
pointer allocate(size_type n, const void *hint=0){
counter += n;
return std::allocator<T>::allocate(n, hint);
}
void deallocate(pointer p, size_type n){
counter -= n;
return std::allocator<T>::deallocate(p, n);
}
static size_t getAllocatedBytes() { return counter;}
countingAllocator() throw(): std::allocator<T>() {}
countingAllocator(const countingAllocator &a) throw(): std::allocator<T>(a) { }
template <class U>
countingAllocator(const countingAllocator<U> &a) throw(): std::allocator<T>(a) { }
~countingAllocator() throw() { }
};
template <int N>
struct big_struct {
char c[N];
};
template<
class Key,
class T,
class Hash = std::hash<Key>,
class KeyEqual = std::equal_to<Key>,
class Allocator = std::allocator< std::pair<const Key, T> >
> class unordered_map;
int main( int argc, char ** argv) {
typedef big_struct<64> data_type;
typedef std::unordered_map<int, data_type*, std::hash<int>, std::equal_to<int>,
countingAllocator< std::pair< const int, data_type*>> > map_type;
map_type m;
for (int i = 0; i < 1000 * 1000; i++) {
m.insert(std::make_pair(i, new data_type));
}
for (map_type::iterator it = m.begin(); it != m.end();) {
delete it->second;
it = m.erase(it);
}
std::cout << "allocated memory before returning " << countingAllocator< std::pair< const int, data_type*>> ::getAllocatedBytes() << std::endl;
return 0;
}
和程序的输出:
allocated memory before returning 1056323
所以基本上这意味着您需要以某种方式调用映射析构函数以正确摆脱先前分配的内存,您可以通过多种方式做到这一点:
- 将 unordered_map 放入
shared_ptr
- 使 unordered_map 超出范围
我在我的PublicProfileTests存储库上上传了配置文件代码,以便您可以贡献