c++ - 为什么容器分配器内部的 sizeof(T) 与单独分配器中的不同?

标签 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 编译器,clang 3.8 为 20 和 56, 或 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 会通过 所需的字节数。然后我模板化了我们的 全局池,但有点笨拙的是全局实例必须 用所需的类型单独初始化 - 这就是 麻烦开始了,那不是正确的类型!我看到了机会 allocate 仅传递项目数而不是字节数。 如您所见,它没有像我尝试的那样工作。我的错误是 在模板化我们的池之后不久,我没有意识到我可以 只需将它的静态实例放入我的分配器模板类中即可。 砰,问题解决了,现在所有的 sizeof 都一致了。游泳池 现在工作正常,它现在是嵌入到 分配器模板类,它比我们的更精简和高效 以前的版本。使用 C++ 约 25 年,模板从未停止让我惊叹。感谢您的帮助。

最佳答案

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

它真的使用TestAllocator<some_internal_node_type>分配对象。这是您获得的节点类型的大小。

关于c++ - 为什么容器分配器内部的 sizeof(T) 与单独分配器中的不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46994204/

相关文章:

c++ - makefile的正确使用

c++ socket read()有时在连接到服务器时返回-1

c++ - 在 QML 中使 QList<QObject*> C++ 模型动态化

c++ - Windows 64 位结构大小随包含的数据类型而变化?

c - VS 2010 中的枚举大小选项

c++ - 如何确定数组长度

Docker 容器 - 选项 "--detach-keys Override the key sequence for detaching a container"是什么意思?

git - 为什么我要从 repo URL 构建 docker?

java - 为什么 .validate() 不会更新此代码中的 contentPane?

c - 指针 - 转换为结构指针 + Malloc