【问题标题】:Can I use stl allocators to make both an entire stl container and it's contents (keys and values) be stored inside a memory block that I created?我可以使用 stl 分配器将整个 stl 容器及其内容(键和值)存储在我创建的内存块中吗?
【发布时间】:2015-12-15 23:31:49
【问题描述】:

我正在尝试了解是否可以使用 stl 分配器 (http://www.drdobbs.com/the-standard-librarian-what-are-allocato/184403759) 或任何其他 C++ 机制来实现我的目的。

我有一个我自己分配的大内存块。

我想创建一个像say map这样的stl容器,这样容器,包括存储在容器中的键和值,都存储在这个内存块中。

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

地图对象本身(不包括上述位)在我的内存块中的存储将由我处理。显然,我无法为我做其他事情。

我知道有些回复可能是“不要”,但请取笑我并假设我有充分的理由想要将所有内容存储在我预先分配的内存块中。

【问题讨论】:

  • 很高兴看到您尝试这样做

标签: c++ memory-management stl allocator


【解决方案1】:

C++ 2003也可以,allocator类写起来并不难,下面是我在vs2005中使用的小例子,在clang下编译采用。它计算某些使用 unordered_map 请求的内存字节数。

ps。您说您有一块内存,您希望自定义分配器从中进行分配,要使其正常工作,您将需要某种分配器来处理频繁的分配/解除分配-为此,您可能需要查看@ 987654321@可以配置使用这样的内存块。

http://coliru.stacked-crooked.com/a/e27368e784123954

#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;
}

【讨论】:

    【解决方案2】:

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

    分配器是一个有点复杂的话题。可以在 Alisdair Meredith 的 CppCon 2014 会谈 part 1part 2 中找到对 C++11 分配器的良好介绍

    C++11 引入了scoped_allocator_adaptor,当您有嵌套的 STL 类型(例如,map&lt;string, vector&lt;string&gt;&gt; 之类的东西)时,这是实现这项工作的重要部分。

    对此有一个警告:没有一种很好的便携方法可以提前确定您的内存块需要多大才能容纳您想要存储在其中的所有内容。为了变得健壮和便携,您需要预先做出“最佳猜测”,然后处理最终需要分配的内存比大块中保留的内存更多的情况。

    【讨论】:

      猜你喜欢
      • 2016-06-07
      • 1970-01-01
      • 2020-08-10
      • 2012-08-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-15
      • 1970-01-01
      相关资源
      最近更新 更多