2014-12-17 5 views
8

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

Например:

class A 
{ 
private: 
    int n; 
    alignas(64) double* ptr;  

public: 
    A(const int num) : n(num), ptr(new double[num]) 
    {} 
}; 

, который я надеялся бы обеспечить данные для PTR был выровнен по 64-байтный блок с. Использование компилятора Intel это не так.

Может ли кто-нибудь указать мне в правильном направлении, пожалуйста?

+5

Кажется, [работает для меня] (http://rextester.com/LCVUW98273) (обратите внимание на необычно большой размер 'A'). Или вы надеялись, что данные 'ptr' будут указывать ** на **, будут выровнены? Это потребует нарушения причинности. –

+0

Возможно, ваш компилятор не поддерживает выравнивание 64? – Brian

+0

Спасибо, Игорь, это показывает источник моего недоразумения. Указатель выровнен, а не данные, на которые он указывает. Я надеялся, что блок данных будет выровнен. – user1683586

ответ

5

Использование ключевого слова alignas(N) на члене класса приводит к тому, что член должен быть выровнен в соответствии с указанным выравниванием, а не любой объект, на который указывает указатель. В конце концов, при инициализации указателя со значением нет элемента управления для выравнивания уже существующих объектов.

Вы можете посмотреть на std::align(), который принимает

  1. спецификация для выравнивания возвращенного указателя.
  2. Размер выровненного блока.
  3. Указатель на выделенную память.
  4. Объем выделенной памяти.

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

+0

Замена 'ptr = x;' с помощью 'ptr = decltype (ptr) (x & ~ uintptr_t (64-1));' гарантирует, что ptr выровнен по 64-байтным границам. По правде говоря, это нехорошо. – Yakk

+0

@Yakk: Я думаю, что использование 'std :: align()' предпочтительно. То, что реализация делает для надлежащего выравнивания понтера, зависит от реализации. Так как ваш подход, вероятно, будет мешать памяти _in front_ указателя, вы, вероятно, захотите сначала скорректировать указатель на подходящую сумму. –

+0

Я думаю, что реальная проблема с моим «решением» заключается в том, что я ушел и модифицировал указатель willy nilly. Указатель выровнен, но он не указывает на что-либо полезное. – Yakk