我想在缓存边界上输入我的类型,所以我使用了alignas
:
struct alignas(64) W { };
编译好。但令我惊讶的是,当我尝试分配一堆W
时,它们不是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)。这是怎么回事?我告诉它要对齐,为什么不对齐?
答案 0 :(得分:3)
这里的回答非常好:https://stackoverflow.com/a/16510895
基本上:new
(至少在其正常使用中)仅保证每次调用alignof(std::max_align_t)
时的最大对齐(new
)。
答案 1 :(得分:2)
另一个答案是正确的,因为它解释了现有的限制,但我想指出事情即将变得更好。
如T.C.所示。在评论中,这是语言的长期缺陷。像looks这样的the WG effort来解决这个问题已经导致了C ++ 17(它刚刚达到特征完整状态)的解决方案。因此,在编译到该标准时,通过使用std::align_val_t
的新new
重载,动态分配将最终尊重整数。从而解决了巴里的问题!
考虑到所需的新脚手架的数量,我认为这不会被反向移植到标准的早期版本,因此关于其动态分配的旧警告仅适用于具有基本对齐的类型可能会保持真实。