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

2 ответа

На этот вопрос приятно ответить здесь: /questions/7688646/dinamicheskoe-vyiravnivanie-pamyati-v-c11/7688651#7688651

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

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

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

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

Другие вопросы по тегам