2013-09-30 2 views
29

В C++ 11 std::array определяется как непрерывное хранилище и производительность, которая не хуже массива, но я не могу решить, подразумевают ли различные требования стандарта что std :: array имеет тот же размер и макет памяти, что и обычный массив. То есть вы можете рассчитывать на sizeof(std::array<int,N>) == sizeof(int)*N или это конкретная реализация?Является ли размер std :: array определенным стандартом

В частности, это гарантированно работать так, как можно было бы ожидать его:

std::vector< std::array<int, N> > x(M); 
typedef (*ArrayPointer)[N]; 
ArrayPointer y = (ArrayPointer) &x[0][0]; 
// use y like normal multidimensional array 

Он работает в двух составителей я попробовал (GNU & Intel). Кроме того, вся документация сторонней стороны, которую я мог найти (like this), утверждает, что std :: array эффективен как память как простой массив, который в сочетании с непрерывным требованием подразумевал бы, что он должен иметь идентичный макет памяти. Однако я не могу найти это требование в стандарте.

+1

В '23.3.2 массив шаблонов нет такой гарантии, и действительно, поиск стандарта для' sizeof', кажется, только для меня включает следующие гарантии: 'char' и его варианты -' 1', и 'nullptr' имеет тот же размер, что и' void * '. – us2012

+0

Как говорится в @ us2012, нет явной гарантии. Хотя он может работать на вашей платформе выбора, он может выйти на другие платформы с различными ограничениями выравнивания. –

ответ

23

Это около. В частности, §23.3.2.1/2 говорит:

Массив представляет собой совокупность (8.5.1), который может быть инициализирован с помощью синтаксиса

array<T, N> a = { initializer-list }; 

, где initializer-list является comma- разделенный список до N элементов, типы которых можно конвертировать в T.

Поскольку это совокупность, он не может использовать какой-либо конструктор для преобразования данных в initializer-list в правильный формат. Это действительно оставляет только одну возможность: единственное, что она может хранить, это сами ценности.

Я полагаю, что бы быть возможно для std::array хранить какие-то вспомогательные данные следующих указанные данные, такие как дополнительная память, установленной в некоторое определенное значение, так что если вы пишете мимо конца массива, вы» d, возможно, измените эти данные. Затем компилятор/время выполнения проверяет эти значения при отключении, а если вы изменили значения, сообщите о неопределенном поведении вашего кода.

Возможно также, что компилятор может сделать дополнение/выравнивание по-разному для std::array, чем для встроенного массива. Одним из очевидных примеров, для которых это может быть даже желательно, будет поддержка требований суперуровневости, таких как данные для использования с инструкциями Intel SSE. Встроенный массив не может поддержка супер-юстиции, но я думаю спецификация std::array может быть достаточно свободной, чтобы позволить ей.

Итог: не доходя до вопросов о том, сколько возможностей может существовать, довольно ясно, что std::array не обязательно должен следовать правилу, о котором вы просите.

+2

Я думаю, что он также может иметь отступы даже в начале, так как не обязательно быть стандартным классом макета (и не может быть, поскольку его члены могут иметь тип нестандартного макета). – dyp

+1

[Живой пример] (http://coliru.stacked-crooked.com/a/34cc30147f6c92c4) (Да, это ничего не доказывает. Я тщательно искал Стандарт и не нашел никаких требований * макета * для агрегатов или). – dyp

+0

C запрещает структурам иметь неназванное дополнение в начале в 6.7.2.1/15 «В объекте структуры может быть неназванное заполнение, но не в самом начале ». (т. е. вы все равно могли бы получить его в конце) – dyp

Смежные вопросы