2016-01-30 3 views
3

По какой-то причине (данные хранятся в виртуальной памяти boost/interprocess/file_mapping.hpp) Я пишу свое собственное распределение памяти. Для обеспечения межплатформенной переносимости я отношусь к выравниванию памяти общего типа T. (Примечание T сильно POD или простой C++ скалярная как char или int) Из примера в http://en.cppreference.com/w/cpp/types/aligned_storage мы можем увидеть следующий код:Выровненный доступ к элементам массива

... 
typename std::aligned_storage<sizeof(T), alignof(T)>::type data[N]; 
std::size_t m_size = 0; 

public: 
    // Create an object in aligned storage 
    template<typename ...Args> void emplace_back(Args&&... args) 
    { 
     if(m_size >= N) // possible error handling 
      throw std::bad_alloc{}; 
     new(data+m_size) T(std::forward<Args>(args)...); 
..... 

Таким образом, вместо регулярного доступа data[i] Я всегда оценивать соответствие адрес.

Так что мой вопрос:

1) Является ли это не накладные расходы? И я могу просто выделить и получить доступ к памяти для (sizeof(data[N]))

2) Если это накладные расходы по причине использования выровненного доступа, показанного в примере?

+0

Я думаю, нам нужен более полный пример, но теперь код, который я вижу, теперь вызывает новое размещение для каждого объекта, что полезно, если они являются объектами, и с достаточной инкрустацией станет «почти ничего». Как всегда, «это медленнее, чем идеал», вам действительно нужно измерить это, а не просто смотреть на код в теории, поскольку компиляторы иногда очень умны, а иногда нет, на основе крошечных деталей. –

+0

Пример статического векторного класса в cppreference содержит массив символов для хранения данных. Отсутствует атрибут выравнивания для символов или массивов символов. Если теперь вы попытаетесь сохранить двойной адрес по произвольно выровненному адресу массива (т. Е. Тот, который не находится, например, на границе 4 байта), программа может потерпеть крах. Поэтому, как правильно указывает @Revolver, массив символов должен начинаться с адреса, который соответствующим образом выровнен для типа (и будет делать все будущие элементы в нем правильно выровненными, тоже без заполнения). –

ответ

0

Не так ли?

Возможно. Возможно, нет. Для большинства типов я ожидаю, что размер aligned_storage::type будет равен размеру указанного типа. И я ожидаю, что компилятор будет оптимизировать доступ не хуже, чем доступ к необработанному массиву.

Я могу только выделить и доступ к памяти для (sizeof(data[N]))
Если накладные расходы, что причина использовать выровнен доступа, показанный в примере?

Да, вы можете выделить сырые памяти (с помощью char массива, например), но вы должны убедиться, что он правильно выровнен для типа вы используете. Это непросто, если вы хотите сохранить некоторый uninitializated массив по значению или выделить некоторую память в стеке. Или если вы используете специализированный распределитель памяти, который не использует new/malloc и не имеет своих свойств адаптации.

aligned_storage Структура - это помощник для автоматизации материалов, которые вы напишете в противном случае.

+0

«Для большинства типов я ожидаю, что размер aligned_storage :: type будет равным содержащемуся типу размера»: Это смешное предположение. Этот класс существует * специально * для случаев, когда, по какой причине, натурное выравнивание недостаточно для потребностей программы. Это означает, что по крайней мере на исходной платформе шансы близки к 1, что размер хранилища больше, чем размер связанного типа. –

+0

@ PeterA.Schneider, я должен не согласиться.Обычно я вижу, что этот класс используется, когда вам нужно сырое хранилище для какого-то типа, которое будет заполнено позже размещением нового. В предоставленном фрагменте вы можете видеть, что аргументы шаблона для aligment - это 'alignof (T)', которые не могут вводить больше накладных расходов, чем исходные массивы (и даже один объект из-за того, как соотносятся размер объекта и положение элементов массива). И если вы действительно посмотрите на полный код, вы увидите, что 'aligned_storage' используется точно так же, как и простое хранилище. –

+0

При ближайшем рассмотрении примера я вижу, что вы правы. Выравнивание необходимо только для внутреннего массива данных, и это всего лишь требование выравнивания типа элемента, не более, не менее, как и для std-вектора, но фиксированного размера. Так что да, я передумаю и буду утверждать, что есть шансы, что нет накладных расходов ;-). –