ключевое слово alignas не соблюдается

Я хочу перенастроить мой тип на границе кэша, поэтому я использовал 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). Что происходит? Я сказал это для выравнивания, почему это не выравнивание?

6

Решение

На это хорошо ответили: https://stackoverflow.com/a/16510895

В принципе: new (по крайней мере, при обычном использовании) только гарантирует постоянное максимальное выравнивание (alignof(std::max_align_t)) за каждый звонок new,

3

Другие решения

Другой ответ является правильным в том смысле, что он объясняет существующее ограничение, но я хотел бы отметить, что ситуация скоро улучшится.

Как указано Т.С. в комментариях это был давний недостаток в языке. Это выглядит лайк усилие РГ исправить это привело к разрешению в C ++ 17 (которое только что достигло состояния полной функциональности). Таким образом, при компиляции к этому стандарту, перераспределение будет в конечном итоге учитываться путем динамического распределения с использованием нового std::align_val_t перегрузки new, Таким образом, решение проблемы Барри!

Учитывая количество новых необходимых лесов, я предполагаю, что это не будет перенесено в более ранние версии Стандарта, поэтому старые предостережение об их динамическом размещении, достаточном только для типов, имеющих фундаментальное выравнивание, предположительно останется верным.

2