在How use alignof to force alignment for a heap allocation? ,我询问了如何将 alignof
用于堆分配的对象。现在我将我的问题归纳为任何强制堆分配对象对齐的方法,因为我找不到使用 alignof
的方法, std::aligned_storage
或 std::align
。以下代码可以编译,但 VC12 和 Clang 3.2 都不会生成零序列作为输出,这表明我的对齐请求得到了尊重。 (gcc 4.8.1 缺少 std::align
,但如果您注释掉该部分,代码将在 gcc 4.8.1 下编译并生成表明我的对齐请求被忽略的输出。)
#include <iostream>
#include <memory>
int main()
{
// Try using alignas on the allocation
{
class Widget {};
for (int i = 0; i < 5; ++i)
{
auto ptr = new alignas(64) Widget;
std::cout << (long)ptr % 64 << '\n'; // should be 0
}
}
// Try using alignas on the type
{
class alignas(64) Widget {};
for (int i = 0; i < 5; ++i)
{
auto ptr = new Widget;
std::cout << (long)ptr % 64 << '\n'; // should be 0
}
}
// Try using std::aligned_storage
{
class Widget {};
using WidgetStorage_t =
std::aligned_storage<sizeof(Widget), 64>::type;
for (int i = 0; i < 5; ++i)
{
auto ptr = new WidgetStorage_t; // get buffer
new (ptr) Widget; // construct Widget
std::cout << (long)ptr % 64 << '\n'; // should be 0
}
}
// Try using operator new + std::align
{
class Widget {};
for (int i = 0; i < 5; ++i)
{
auto requestSize = // double space to ensure that a
2 * sizeof(Widget); // Widget fits after ptr adjustment
auto ptr = operator new(requestSize); // get buffer
std::align(64, sizeof(Widget), // align ptr
ptr, requestSize); // inside buffer
new (ptr) Widget; // construct Widget
std::cout << (long)ptr % 64 << '\n'; // should be 0
}
}
}
更新:上面我用于测试 std::align
的代码不正确。以下替换代码有效:
// Try using operator new + std::align
{
class Widget {};
for (int i = 0; i < 5; ++i)
{
auto requestSize = // ensure that a
sizeof(Widget) + 64; // Widget fits after ptr adjustment
auto ptr = operator new(requestSize); // get buffer
std::align(64, sizeof(Widget), // align ptr
ptr, requestSize); // inside buffer
new (ptr) Widget; // construct Widget
std::cout << (long)ptr % 64 << '\n'; // should be 0
}
}
这是完成工作的唯一方法吗?它比我想要的要复杂得多,因为现在必须跟踪两个指针:指向对象的已调整指针(销毁构造对象所必需的)和指向内存缓冲区的未调整指针(释放所必需的)内存)。
最佳答案
我在实践中看到的一个选择是过度分配,然后自行调整。
例如,假设您要分配 N 字节,与 M 字节边界对齐。您可以继续分配 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
关于c++ - 如何强制对齐堆分配的对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21896311/