如果我创建一个静态const std :: map,它将在堆上分配内存。以下代码抛出bad_alloc:
#include <iostream>
#include <map>
class A {
public:
static const std::map<int, int> a;
};
const std::map<int, int> A::a = { { 1, 3} , { 2, 5} };
void* operator new ( std::size_t count )
{
throw std::bad_alloc();
}
int
main (void)
{
for(auto &ai: A::a) {
std::cout << ai.first << " " << ai.second << "\n";
}
return 0;
}
是否可以在不进行内存分配的情况下以某种方式创建此常量映射?
答案 0 :(得分:0)
正如Igor Tandetnik建议的那样,自定义分配器可以解决问题。以下是一个简单线性分配器的快速简单示例,它从静态缓冲区返回内存插槽:
#include <iostream>
#include <map>
#include <cassert>
template <typename T>
class LinearAllocator {
static constexpr size_t _maxAlloc = 1<<20;
using Buffer = std::array<T, _maxAlloc>;
using FreeList = std::array<bool, _maxAlloc>;
static Buffer _buffer;
static FreeList _allocated;
public:
typedef T* pointer;
typedef T value_type;
template<typename U>
struct rebind { typedef LinearAllocator<U> other; };
pointer allocate(size_t /*n*/, const void *hint=0) {
for(size_t i = 0; i < _maxAlloc; ++i) {
if(!_allocated[i]) {
_allocated[i] = true;
return &_buffer[i];
}
}
throw std::bad_alloc();
}
void deallocate(pointer p, size_t /*n*/) {
assert(p >= &_buffer[0] && p < &_buffer[_maxAlloc]);
_allocated[p-&_buffer[0]] = false;
}
LinearAllocator() throw() { }
LinearAllocator(const LinearAllocator &a) throw() { }
template <class U>
LinearAllocator(const LinearAllocator<U> &a) throw() { }
~LinearAllocator() throw() { }
};
template <typename T>
typename LinearAllocator<T>::Buffer LinearAllocator<T>::_buffer;
template <typename T>
typename LinearAllocator<T>::FreeList LinearAllocator<T>::_allocated;
using MyMap = std::map<int, int, std::less<int>,
LinearAllocator<std::pair<int,int> > >;
// make sure we notice if new gets called
void* operator new(size_t size) {
std::cout << "new called" << std::endl;
}
int main() {
MyMap m;
m[0] = 1; m[1] = 3; m[2] = 8;
for(auto & p : m)
std::cout << p.first << ": " << p.second << std::endl;
return 0;
}
输出:
0: 1
1: 3
2: 8
请注意,此分配器一次只能处理单个插槽的请求。我确定你会根据你的要求弄清楚如何扩展它。