为什么我的容器分配器中的 sizeof(T) 与单独的分配器中的 sizeof(T) 不同?
Why is sizeof(T) different inside my container allocator than in the allocator alone?
在此代码中,如果分配器 是容器分配的一部分:
#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
一些在线编译器结果:
VC++在 webcompiler.cloudapp.net 说20和36。
coliru.stacked-crooked.com 的科里鲁说 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
仅传递项目数而不是字节数。 正如你所看到的,它没有按照我尝试的方式工作。我的错误是 在模板化我们的游泳池后不久,我没有意识到我可以 只需将它的静态实例放在我的分配器模板类中即可。 轰,问题解决了,现在所有的大小都是一致的。游泳池 现在工作正常,它现在是嵌入到 分配器模板类,它比我们的更精简和高效 以前的版本。~25 年的C++,模板从未停止让我惊叹。感谢您的帮助。
multiset
不直接存储Item
,而是使用一些树结构来添加额外的指针来在树中导航。
它实际上使用TestAllocator<some_internal_node_type>
来分配对象。这是您获得的节点类型的大小。
将显示函数修改为:
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
这应该可以消除您的困惑。 多集使用的模板类型是本身包含Item
的节点类。 检查实现的 multiset 标头可能有助于查看分配器何时绑定和使用。
- 当有分配器意识的容器被复制/移动时,反弹分配器是否被复制/移走
- 将 std::allocate_shared 与多态资源分配器一起使用
- 尝试将lambda函数放在队列中时出现一般分配器错误(可能是与unique_ptr有关的错误)
- C++17 - 使用自定义分配器的节点提取/重新插入 - 适用于 clang++/libc++,但不适用于 libstd
- 如何使我的 sizeof sum 结构与空参数包一起工作
- 同一对象的"sizeof"的不同答案
- 使用 std::分配器在 constexpr 中进行默认初始化
- 使用不兼容的分配器复制分配无序列图
- 为什么数组大小信息可用于"sizeof"运算符和 delete[] 运算符,但在将数组作为参数传递到
- C++:矢量分配器行为、内存分配和智能指针
- 为什么 sizeof 在 C++ 中给出不正确的字节数?
- sizeof(size_t) 可以小于 sizeof(int) 吗?
- 是否可以使用分配器对象来释放另一个分配器分配的内存?
- 使用模板化分配器和对向量进行排序的函数
- C++ 中的分配器错误
- 字符串数组上的 sizeof 运算符以 C++ 为单位给出不同的输出
- 基于浅树的数据结构的内存分配器,用于频繁分配和解除分配
- 通过引用传递向量是请求 std::分配器
- 为什么 sizeof(ar)/ sizeof(ar[0]) 在传递给函数时无法在向量上正常工作?
- 为什么我的容器分配器中的 sizeof(T) 与单独的分配器中的 sizeof(T) 不同?