我想在缓存边界上过度对齐我的类型,所以我使用了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,当当3.7.1)。出什么事啦?我告诉它要对齐,为什么它不对齐?
发布于 2016-07-01 04:47:16
这里很好地回答了这个问题:https://stackoverflow.com/a/16510895
基本上:new (至少在正常使用情况下)只保证每个对new的调用都有一个恒定的最大对齐(alignof(std::max_align_t))。
发布于 2016-07-01 05:26:08
另一个答案是正确的,因为它解释了现有的限制,但我想指出的是,事情即将变得更好。
正如T.C.在评论中指出的那样,这是语言中一个长期存在的缺陷。它像the WG effort一样解决了这个问题,导致了C++17中的一个解决方案(它刚刚达到了功能完整状态)。因此,当编译到该标准时,通过使用new的新std::align_val_t重载,动态分配最终将遵守过度对齐。这样就解决了巴里的问题!
考虑到所需的新脚手架的数量,我假设这不会被移植到标准的早期版本,所以关于它们的动态分配仅适用于具有基本对齐的类型的旧警告可能仍然有效。
https://stackoverflow.com/questions/35365624
复制相似问题