我可以使用stl分配器生成整个stl容器和它';的内容(键和值)是否存储在我创建的内存块中? 我试图理解我是否可以使用STL分配器()或其他C++机制来实现我的目的。

我可以使用stl分配器生成整个stl容器和它';的内容(键和值)是否存储在我创建的内存块中? 我试图理解我是否可以使用STL分配器()或其他C++机制来实现我的目的。,c++,memory-management,stl,allocator,C++,Memory Management,Stl,Allocator,我自己分配了一个大内存块 我想创建一个类似saymap的stl容器,使容器(包括存储在容器中的键和值)存储在这个内存块中 明确地说,当我说“容器,包括键和值”时,我指的是通常由容器中的代码在堆上分配的所有内存位。例如,图形结构以及键和值的副本 映射对象本身(不包括上述位)在内存块中的存储将由我处理。显然,我找不到别的东西来帮我 我意识到有些回答可能是“不要”,但请幽默地告诉我,并假设我有充分的理由希望将所有内容存储在我预先分配的内存块中。简短回答,是的,您可以使用C++11分配器来实现这一点 分

我自己分配了一个大内存块

我想创建一个类似saymap的stl容器,使容器(包括存储在容器中的键和值)存储在这个内存块中

明确地说,当我说“容器,包括键和值”时,我指的是通常由容器中的代码在堆上分配的所有内存位。例如,图形结构以及键和值的副本

映射对象本身(不包括上述位)在内存块中的存储将由我处理。显然,我找不到别的东西来帮我


我意识到有些回答可能是“不要”,但请幽默地告诉我,并假设我有充分的理由希望将所有内容存储在我预先分配的内存块中。

简短回答,是的,您可以使用C++11分配器来实现这一点

分配器是一个有点复杂的主题。Alisdair Meredith的CppCon 2014讲座和

介绍了C++11,当您有嵌套的STL类型(例如
map
)时,这是实现此功能的一个重要部分


然而,需要注意的是:没有一个好的可移植方法可以预先确定内存块需要多大才能容纳您想要存储在内存块中的所有内容。要保持健壮性和可移植性,您需要事先做出“最佳猜测”,然后处理这样一种情况,即您最终需要分配的内存超过了所保留的内存在你的大块中,

你也可以用C++ 2003来完成,分配器类并不难编写,下面是我在VS2005中使用的一个小例子,并在CLAN下编译使用。它计算了内存字节的数量。 注:你说你有一个内存块,你想让你的自定义分配器从中进行分配,要使它工作,你需要有某种分配器来处理频繁的分配/解除分配-为此,你可能想检查哪些可以配置为使用这样的内存块

#包括
#包括
#包括
#包括
#包括
int total_alloc=0;
模板
类MyAllocator{
公众:
//类型定义
类型定义T值_类型;
typedef T*指针;
typedef const T*const_指针;
typedef T&reference;
类型定义常数T和常数U参考;
typedef std::size\u t size\u type;
typedef std::ptrdiff_t difference_type;
//将分配器重新绑定到类型U
模板
结构重新绑定{
typedef MyAllocator其他;
};
//返回值的地址
指针地址(参考值)常数{
回报与价值;
}
常量指针地址(常量参考值)常量{
回报与价值;
}
/*构造函数和析构函数
*-无需执行任何操作,因为分配器没有状态
*/
MyAllocator()抛出(){
}
MyAllocator(constmyallocator&)throw(){
}
模板
MyAllocator(constmyallocator&)throw(){
}
~MyAllocator()抛出(){
}
//返回可分配的最大元素数
大小\类型最大大小()常量抛出(){
返回(std::numeric_limits::max)(/sizeof(T);
}
//分配但不初始化t类型的num元素
指针分配(大小\类型num,常量void*=0){
指针ret=(指针)malloc(num*sizeof(T));
总分配+=num*sizeof(T);
返回ret;
}
//用value初始化已分配存储器p的元素
无效构造(指针p、常量T和值){
::新的((空*)p)T(值);
}
//销毁初始化的存储器p的元素
无效销毁(指针p){
//通过调用对象的析构函数来销毁对象
p->~T();
}
//取消分配已删除元素的存储空间
无效解除分配(指针p,大小\类型num){
总分配-=num*sizeof(T);
自由基(p);
}
};
///返回此分配器的所有专门化都是可互换的
模板
布尔运算符==(常量MyAllocator&,
常量MyAllocator&)throw(){
返回true;
}
模板
布尔运算符!=(常量MyAllocator&,
常量MyAllocator&)throw(){
返回false;
}
typedef std::基本字符串stringx;
名称空间标准
{
模板
结构散列{
size\u t运算符()(常量stringx&str)常量{
std::hash str_hash;
返回str_散列(str.c_str());
}
};
}
typedef std::无序映射样本映射类型;
int main()
{
样本映射类型样本映射;
样本映射[“test1”]=1;
样本映射[“test2”]=2;
用于(自动元素:示例地图){

std::能看到您尝试这样做会很好吗
#include <iostream>
#include <string>
#include <memory>
#include <unordered_map>
#include <limits>

int total_alloc = 0;

template <class T>
class MyAllocator {
public:
  // type definitions
  typedef T        value_type;
  typedef T*       pointer;
  typedef const T* const_pointer;
  typedef T&       reference;
  typedef const T& const_reference;
  typedef std::size_t    size_type;
  typedef std::ptrdiff_t difference_type;

  // rebind allocator to type U
  template <class U>
  struct rebind {
    typedef MyAllocator<U> other;
  };

  // return address of values
  pointer address(reference value) const {
    return &value;
  }
  const_pointer address(const_reference value) const {
    return &value;
  }

  /* constructors and destructor
  * - nothing to do because the allocator has no state
  */
  MyAllocator() throw() {
  }
  MyAllocator(const MyAllocator&) throw() {
  }
  template <class U>
  MyAllocator(const MyAllocator<U>&) throw() {
  }
  ~MyAllocator() throw() {
  }

  // return maximum number of elements that can be allocated
  size_type max_size() const throw() {
    return (std::numeric_limits<size_t>::max)() / sizeof(T);
  }

  // allocate but don't initialize num elements of type T
  pointer allocate(size_type num, const void* = 0) {
    pointer ret = (pointer)malloc(num*sizeof(T));
    total_alloc += num*sizeof(T);
    return ret;
  }

  // initialize elements of allocated storage p with value value
  void construct(pointer p, const T& value) {
    ::new((void*)p) T(value);
  }

  // destroy elements of initialized storage p
  void destroy(pointer p) {
    // destroy objects by calling their destructor
    p->~T();
  }

  // deallocate storage p of deleted elements
  void deallocate(pointer p, size_type num) {
      total_alloc -= num*sizeof(T);
    free(p);
  }
};

/// return that all specializations of this allocator are interchangeable
template <class T1, class T2>
bool operator== (const MyAllocator<T1>&,
  const MyAllocator<T2>&) throw() {
  return true;
}
template <class T1, class T2>
bool operator!= (const MyAllocator<T1>&,
  const MyAllocator<T2>&) throw() {
  return false;
}

typedef std::basic_string<char, std::char_traits<char>, MyAllocator<char> > stringx;

namespace std
{
template<>
struct hash<stringx> {
    size_t operator()(const stringx &str) const {
        std::hash<const char*> str_hash;
        return str_hash(str.c_str());
    }
};
}

typedef std::unordered_map<stringx, int,
  std::hash<stringx>,
  std::equal_to<stringx>,
  MyAllocator<std::pair<const stringx, std::pair<stringx, int> > > > sample_map_type;

int main()
{
  sample_map_type sample_map;
  sample_map["test1"] = 1;
  sample_map["test2"] = 2;
  for (auto elem : sample_map) {
    std::cout << elem.first << " -> " << elem.second << std::endl;
  }
  std::cout << "total_alloc = " << total_alloc << std::endl;
}