在这段代码中,如果分配器,我得到一个不同的 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:
为了那些使用分配池的人的利益:
耶!我想我达到了我的目标。示例代码基于
在真实的应用程序上,正如您所料,分配器模板的
allocate
和deallocate
不只是调用new
和delete
。
他们交给一个游泳池。直到星期四,这个游泳池是全局性的
分块式多维(几个不同的平面
对于常见的预期大小请求)。 allocate
会通过
所需的字节数。然后我模板化了我们的
全局池,但有点笨拙的是全局实例必须
用所需的类型单独初始化 - 这就是
麻烦开始了,那不是正确的类型!我看到了机会
allocate
仅传递项目数而不是字节数。
如您所见,它没有像我尝试的那样工作。我的错误是
在模板化我们的池之后不久,我没有意识到我可以
只需将它的静态实例放入我的分配器模板类中即可。
砰,问题解决了,现在所有的 sizeof 都一致了。游泳池
现在工作正常,它现在是嵌入到
分配器模板类,它比我们的更精简和高效
以前的版本。使用 C++ 约 25 年,模板从未停止让我惊叹。感谢您的帮助。
最佳答案
multiset
不存储 Item
s 直接,但使用一些树结构,添加额外的指针以在树中导航。
它真的使用TestAllocator<some_internal_node_type>
分配对象。这是您获得的节点类型的大小。
关于c++ - 为什么容器分配器内部的 sizeof(T) 与单独分配器中的不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46994204/