为什么我的容器分配器中的sizeof(T)与单独的分配器不同?

时间:2017-10-28 20:32:09

标签: c++ containers sizeof pool allocator

在这段代码中,如果分配器,我得到一个不同的sizeof(T)  是容器分配的一部分:

#include <iostream>
#include <set>
#include <cstddef>


class Item
{
    int a;
    unsigned char b, c, d;
    int e, f, g;

  public:
    Item() { a = b = c = d = e = f = g = 0; }
    bool operator<(const Item& item) const { return item.a < a; }
};

template <typename T> class TestAllocator
{
  public:
    typedef T         value_type;
    typedef size_t    size_type;
    typedef ptrdiff_t difference_type;

    typedef T*        pointer;
    typedef const T*  const_pointer;

    typedef T&        reference;
    typedef const T&  const_reference;

    pointer address(reference x) const { return &x; }
    const_pointer address(const_reference x) const { return &x; }

    TestAllocator() { std::cout << "TestAllocator ctor: sizeof T:" << sizeof(T) << std::endl; }

    template <typename U> TestAllocator(const TestAllocator<U>&) {}
    ~TestAllocator() {}

    pointer allocate(size_type /*n*/, void * = 0) { return static_cast<T*>(new T()); }

    void deallocate(pointer p, size_type /*n*/) { delete p; }

    TestAllocator<T>&  operator=(const TestAllocator&) { return *this; }
    void construct(pointer p, const T& val) { new ((T*) p) T(val); }
    void destroy(pointer p) { p->~T(); }
    size_type max_size() const { return size_t(-1); }

    template <typename U> struct rebind { typedef TestAllocator<U> other; };
    template <typename U> TestAllocator& operator=(const TestAllocator<U>&) { return *this; }
};


typedef std::multiset<Item, std::less<Item>, TestAllocator<Item> > ItemMultiset;


int main(int /*argc*/, char** /*argv*/) 
{
  std::cout << "Instantiating allocator:" << std::endl;
  TestAllocator<Item> ta;

  std::cout << "Instantiating container:" << std::endl;
  ItemMultiset ims;

  return 0;
}

在我的gcc 7.2.1上,我得到了:

Instantiating allocator:
TestAllocator ctor: sizeof T:20
Instantiating container:
TestAllocator ctor: sizeof T:56

一些在线编译器的结果:

webcompiler.cloudapp.net上的VC ++说20和36。

coliru.stacked-crooked.com的Coliru说20和56  对于所有选定的gcc编译器,20和56用于clang 3.8,  或者20和48为clang 3.8 C ++ 11/14。

为什么差异,为什么有些结果填充每个结构成员?

如何询问容器的对齐'模式'和  将它应用于我的结构或代码,或者我怎么能告诉它  容器使用我的代码模式,以确保结果  永远相同?

编辑:感谢您在下面的快速回复。

哇,使用了很多空间。其他容器的进一步结果:

Instantiating allocator:
TestAllocator ctor: sizeof T:20

Instantiating multiset:
TestAllocator ctor: sizeof T:56

Instantiating multimap:
TestAllocator ctor: sizeof T:20

Instantiating list:
TestAllocator ctor: sizeof T:40

Instantiating vector:
TestAllocator ctor: sizeof T:20 

编辑2:

为了使用分配池的人的利益:

耶!我想我实现了目标。示例代码基于  在一个真正的应用程序上,正如您所料,分配器模板的  allocatedeallocate不只是致电newdelete。  他们把手送到游泳池。直到周四,游泳池才是全球性的  分块式多维(几个不同的平面  对于共同预期的大小要求)。 allocate会通过  所需的字节数。然后我模板化了我们的  全局池,但有点笨拙的全局实例必须  用所需的类型单独初始化 - 就在那里  麻烦开始了,那不是正确的类型!我看到了机会  for allocate只传递项目数而不是字节数。  如你所见,它没有像我尝试的那样工作。我的错误是  模板化我们的游泳池后不久,我没有意识到我能做到  只需在我的allocator模板类中删除它的静态实例。 繁荣,问题解决了,现在所有的尺寸都是一致的。游泳池  现在工作正常,它现在是嵌入到的模板  分配器模板类,它比我们更精简和高效  以前的版本。使用C ++约25年,模板永远不会让我惊讶。谢谢你的帮助。

2 个答案:

答案 0 :(得分:3)

multiset不直接存储Item,但使用一些树结构,添加额外的指针以在树中导航。

它确实使用TestAllocator<some_internal_node_type>来分配对象。它是节点类型的大小。

答案 1 :(得分:2)

将显示功能修改为:

TestAllocator() { std::cout << "TestAllocator ctor: sizeof T:" << sizeof(T) << " ," << typeid(T).name() << std::endl; }

我得到输出:

Instantiating allocator:
TestAllocator ctor: sizeof T:20, 4Item
Instantiating container:
TestAllocator ctor: sizeof T:56, St13_Rb_tree_nodeI4ItemE

这应该可以消除你的困惑。 multiset使用的模板类型是一个节点类,它本身包含Item。检查实现的多集标题可能有助于查看绑定和使用分配器的时间。

相关问题