7

我想在缓存边界上过度对齐我的类型,所以我使用了alignas

struct alignas(64) W { };

这编译得很好。但是,令我惊讶的是,当我尝试分配一堆Ws 时,它们不是 64 字节对齐的,而是实际上是 16 字节对齐的:

#include <iostream>
#include <iomanip>
#include <unordered_map>

struct alignas(64) W { };

int main() {
    std::unordered_map<int, int> offset;

    for (int i = 0; i < 1000; ++i) {
        auto w = new W;
        offset[(uintptr_t)w % 64]++;
    }   

    for (const auto& p : offset) {
        std::cout << p.first << ' ' << p.second << '\n';
    }   
}

产量:

0 250
16 250
32 250
48 250

在几个编译中(gcc 4.8.2、gcc 5.2.0、clang 3.7.1)。这是怎么回事?我告诉它对齐,为什么它不对齐?

4

2 回答 2

3

这在这里得到了很好的回答:https ://stackoverflow.com/a/16510895

基本上:(new至少在正常使用中)只保证alignof(std::max_align_t)每次调用new.

于 2016-06-30T20:47:16.413 回答
2

另一个答案是正确的,因为它解释了现有的限制,但我想指出事情即将好转。

正如 TC 在评论中指出的那样,这是语言中长期存在的缺陷。看起来WG 解决此问题的努力已导致C++17 中的解决方案(刚刚获得功能完整状态)。std::align_val_t因此,当编译到该标准时,过度对齐最终将通过动态分配得到尊重,通过使用new. 从而解决巴里的问题!

鉴于所需的新脚手架数量,我认为这不会被向后移植到标准的早期版本,因此关于它们的动态分配仅适用于具有基本对齐的类型的旧警告可能仍然适用。

于 2016-06-30T21:26:08.230 回答