我的问题很简单;
alignas说明符是否适用于'new'?也就是说,如果一个结构被定义为对齐,那么在分配新的时候它是否会对齐?
答案 0 :(得分:12)
如果类型的对齐没有过度对齐,那么是,默认的new
将起作用。 “过度对齐”表示您在alignas
中指定的对齐方式大于alignof(std::max_align_t)
。默认new
或多或少会偶然使用非过度对齐的类型;默认内存分配器将始终使用等于alignof(std::max_align_t)
的对齐方式分配内存。
如果你的类型对齐过度对齐,那么你的运气不好。您编写的默认new
或任何全局new
运算符都不能知道该类型所需的对齐,更不用说分配适合它的内存。帮助这种情况的唯一方法是重载类的operator new
,它将能够查询类与alignof
的对齐。
当然,如果该类用作另一个类的成员,这将没有用。除非其他类也重载operator new
。所以像new pair<over_aligned, int>()
这样简单的东西是行不通的。
C ++ 17的提案(已被接受)通过使operator new/delete
的重载采用所分配类型的alignof
来添加support for dynamic allocation of over-aligned types。这也将支持小于最大对齐类型的对齐,因此您的内存分配器不必总是返回与alignof(std::max_align_t)
对齐的内存。
话虽如此,编译器并非必需来支持过度对齐的类型。
答案 1 :(得分:11)
不,不。结构将填充到请求的对齐方式,但不会对齐。但是,有可能这将是allowed in C++17(这个C ++ 17提议存在的事实应该很好地证明这在C ++ 11中不起作用。)
我已经看到这似乎适用于一些内存分配器,但那是纯粹的运气。例如,一些内存分配器会将它们的内存分配与请求大小的2的幂(最多4KB)对齐,作为分配器的优化(减少内存碎片,可能更容易重用以前释放的内存等等) 。但是,我测试的OS X 10.7和CentOS 6系统中包含的new / malloc实现不会这样做,并且使用以下代码失败:
#include <stdlib.h>
#include <assert.h>
struct alignas(8) test_struct_8 { char data; };
struct alignas(16) test_struct_16 { char data; };
struct alignas(32) test_struct_32 { char data; };
struct alignas(64) test_struct_64 { char data; };
struct alignas(128) test_struct_128 { char data; };
struct alignas(256) test_struct_256 { char data; };
struct alignas(512) test_struct_512 { char data; };
int main() {
test_struct_8 *heap_8 = new test_struct_8;
test_struct_16 *heap_16 = new test_struct_16;
test_struct_32 *heap_32 = new test_struct_32;
test_struct_64 *heap_64 = new test_struct_64;
test_struct_128 *heap_128 = new test_struct_128;
test_struct_256 *heap_256 = new test_struct_256;
test_struct_512 *heap_512 = new test_struct_512;
#define IS_ALIGNED(addr,size) ((((size_t)(addr)) % (size)) == 0)
assert(IS_ALIGNED(heap_8, 8));
assert(IS_ALIGNED(heap_16, 16));
assert(IS_ALIGNED(heap_32, 32));
assert(IS_ALIGNED(heap_64, 64));
assert(IS_ALIGNED(heap_128, 128));
assert(IS_ALIGNED(heap_256, 256));
assert(IS_ALIGNED(heap_512, 512));
delete heap_8;
delete heap_16;
delete heap_32;
delete heap_64;
delete heap_128;
delete heap_256;
delete heap_512;
return 0;
}