Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/141.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何强制堆分配对象的对齐?_C++_C++11_Memory Alignment - Fatal编程技术网

C++ 如何强制堆分配对象的对齐?

C++ 如何强制堆分配对象的对齐?,c++,c++11,memory-alignment,C++,C++11,Memory Alignment,在中,我询问如何对堆分配的对象使用alignof。现在,我将我的问题概括为任何强制对齐堆分配对象的方法,因为我找不到使用alignof、std::aligned\u storage或std::align的方法。下面的代码经过编译,但VC12和Clang 3.2都不会生成零序列作为输出,这表明我的对齐请求得到了尊重。(gcc 4.8.1缺少std::align,但如果您注释掉该部分,代码将在gcc 4.8.1下编译,并生成输出,指示我的对齐请求被忽略。) 这是完成工作的唯一方法吗?这比我想要的要复

在中,我询问如何对堆分配的对象使用
alignof
。现在,我将我的问题概括为任何强制对齐堆分配对象的方法,因为我找不到使用
alignof
std::aligned\u storage
std::align
的方法。下面的代码经过编译,但VC12和Clang 3.2都不会生成零序列作为输出,这表明我的对齐请求得到了尊重。(gcc 4.8.1缺少
std::align
,但如果您注释掉该部分,代码将在gcc 4.8.1下编译,并生成输出,指示我的对齐请求被忽略。)


这是完成工作的唯一方法吗?这比我想要的要复杂得多,因为现在必须跟踪两个指针:指向对象的调整指针(销毁构造对象所必需的)和指向内存缓冲区的未调整指针(释放内存所必需的)。

我在实践中看到的一个选项是过度分配,然后为自己调整事情

例如,假设您要分配与M字节边界对齐的N个字节。您可以通过分配N+M-1字节继续,然后在分配的空间中找到第一个M字节对齐的地址。例如,您可以执行以下操作:

const size_t N = sizeof(Widget);
const size_t M = 64;
char *pc = new char[N+M-1];
char *pc_aligned = (pc+M-1)&(~(M-1));
Widget *p = new (pc_aligned) Widget();    // placement new
// ...
p->~Widget();                             // explicitly call destructor
delete [] pc;                             // delete array allocated with new

MS清楚地记录了C++11
alignas

对于GNU,如果你把它放在正确的位置,它似乎是有效的——从一个角度来看——更多的例子和讨论请参见该答案:

typedef float aligned_block alignas(16) [4];
typedef float aligned_block [4] alignas(16);

我的理解是,
std::align
就是为这种事情而设计的。@KnowItAllWannabe-Correct,但是现在缺少
std::align
仍然是很常见的。我没有看到任何与堆对象相关的例子。我是否忽略了它们?@KnowItAllWannabe如果你告诉编译器需要对象的特定对齐方式,
new
必须遵守这一点,直到
alignof(std::max\u align\t)
,超过这一点如果分配器不支持与特定过度对齐类型关联的对齐,则该类型的分配器实例化可能会失败。分配器也可以静默地忽略请求的对齐。,这基本上意味着您又回到了按照SchighSchagh的答案手动编排的状态。这个答案的主旨是描述编译器对
alignas
的支持和符号。我相信您引用的文本只适用于STL分配器,而不适用于
运算符new
。我希望3.11/9在这里适用:“如果实现不支持在特定上下文中对特定扩展对齐的请求,则该程序的格式不正确。此外,对于无法执行所请求对齐的动态存储的运行时分配请求,应将其视为分配失败。”默认的
操作符new
是标准库容器的默认分配器,因此它必须至少满足相同的要求。虽然-3.11/9看起来很适用:“如果……不受支持……格式不正确”意味着如果不受支持,他们必须发出警告消息。如果你有耐心和乐观的话,你仍然可以尝试为编译器提交bug报告。顺便说一句,根据,2013年11月CTP版本的MS编译器支持
alignas
。你有什么奇怪的代码
类alignas(64)Widget{}?这就是说
Widget
对象具有64字节对齐方式,尽管它似乎对堆对象没有任何影响。空的花括号是类的主体。对于这个例子,我不关心类中有什么。您是否考虑过编写一个特定于类型的
操作符new[]
,而不是强迫每个分配位置担心对齐?我感兴趣的是,是否有一种方法可以基于每个对象(而不是您建议的每个类型)来实现这一点。对于非堆对象,这显然是可能的(通过
alignas
)。对于堆对象,
alignas
似乎没有任何效果(对于对象和类型)。每个对象?上面带有分配代码的函数给出了简洁的用法,剩下的问题是。。。?也许要
删除
指针,而客户端代码不必担心指针是否被调整了?唯一的方法是:重写
delete
,以可能将指针调整回最初提供的预扩展对齐值
new
(需要记账),或者确保只使用充分对齐的值
new
返回值(例如,循环以丢弃对齐度较低的指针,但您可以循环多长时间?). Sans
delete
,可以使用为调用者提供自定义智能指针。
const size_t N = sizeof(Widget);
const size_t M = 64;
char *pc = new char[N+M-1];
char *pc_aligned = (pc+M-1)&(~(M-1));
Widget *p = new (pc_aligned) Widget();    // placement new
// ...
p->~Widget();                             // explicitly call destructor
delete [] pc;                             // delete array allocated with new
typedef float aligned_block alignas(16) [4];
typedef float aligned_block [4] alignas(16);