【发布时间】:2017-03-17 12:30:22
【问题描述】:
我想在另一个分配器(通常在内部调用 realloc)返回的内存中构造任意 C++ 对象。我知道在 malloc 的内存中做一个新的放置通常是可以的。但是,我希望所有 C++ 对象在连续分配的内存中都有另一个公共对象。此标头对象将包含有关以下 C++ 对象的信息。从对齐的角度来看,我不知道分配 (sizeof(header) + sizeof(type)) 内存然后在 (mem + sizeof(header)) 处构造类型是否安全。我认为这不是因为 (mem + sizeof(header)) 不能保证正确对齐类型。
我考虑了一些可能性,例如生成一个模板类型,该模板类型声明标头,后跟类型 T 并分配 sizeof(ObjPlusHeader<T>)。但是,问题是该结构将作为 void* 出现在我的代码的另一部分中(由我无法控制的外部库强制执行),因此我必须知道将其转换为什么。我想转换为 Header* 而不是ObjectPlusHeader<???>*。
我知道使用标准布局类型,我可以将对象转换为指向其第一个成员的指针。但是,T 不一定是标准布局,在这种情况下,ObjectPlusHeader<T> 也不会是标准布局,即使 Header 是。我还考虑过让包装器模板从 Header 公开派生,从 T 私下派生而不是包含 T。但是,将 void* 直接转换为 Header* 而不首先转换为存储的实际类型仍然是不合法的我不会知道的。
我想要的是由分配器(基本上是 realloc)分配的连续内存,我知道 Header 位于开头,并且任意 C++ 对象跟随在我知道并可以存储的某个正确对齐的地址 >= mem + sizeof(Header)在标题中。所以给定 void* 我可以将它转换为 Header* 并获取对象。但是,我不确定潜在的对齐问题。
【问题讨论】:
-
如果对象应该捆绑在一起,请将它们存储为
std::pair -
@NathanOliver。确实,但是当 T 不一定是标准布局时,将 std::pair
* 转换为 Header* 是否安全?你看,问题的第二部分是我不知道这对的实际类型。我需要保证我可以转换为 Header* 并从那里开始。 -
你为什么不通过alignof获得所需的对齐并相应地调整指针?即自己添加正确的填充量。
-
@authentec 子类化怎么样?绝对允许向/从
Header的(模板)子类进行转换。 -
@o11c 是的,但不幸的是我不控制存储的指针值。分配库允许我请求任意大小的内存块,它给了我一个指向它的指针,我可以在其中写入我想要的内容(使用子类化方法,这将是最派生的对象) T 子对象)。在某些时候,它可能会将指向它分配为 void* 的内存的指针交还给我。我别无选择,只能将它投射到我写进记忆的任何东西上。那是
Derived<T>*,但那时我不知道 T。