static_assert(sizeof(std::array<int,5>)==5*sizeof(int));
вышеупомянутое смягчает против наличия любого дополнения на конце std::array
. Ни один крупный компилятор не приведет к сбою вышеизложенного до этой даты, и я готов поспорить, что в будущем это не так.
Если и только если вышеперечисленное не сработало, то std::vector<std::array<int,5>> v(2)
будет иметь «пробел» между std::array
с.
Это не так много, как хотелось бы; указатель, сгенерированный следующим образом:
int* ptr = &v[0][0];
имеет область действия только до ptr+5
, а разыменование ptr+5
- неопределенное поведение.
Это связано с правилами наложения имен; вам не разрешается "проходить" через конец одного объекта в другой, даже если вы знаете, что он там есть, если только вы не совершите первое круговое путешествие к определенным типам (например, char*
), где разрешена менее ограниченная арифметика указателей.
Это правило, в свою очередь, существует, чтобы позволить компиляторам рассуждать о том, к каким данным осуществляется доступ через какой указатель, без необходимости доказывать, что арифметика произвольного указателя позволит вам достичь внешних объектов.
Итак:
struct bob {
int x,y,z;
};
bob b {1,2,3};
int* py = &b.y;
независимо от того, что вы делаете с py
как int*
, вы не можете юридически изменить x
или z
с ним.
*py = 77;
py[-1]=3;
std::cout << b.x;
компилятор может оптимизировать строку std::cout
, чтобы просто напечатать 1
, поскольку py[-1]=3
может попытаться изменить b.x
, но это означает, что поведение не определено.
Подобные ограничения не позволяют вам перейти от первого массива в вашем std::vector
ко второму (т. Е. За пределы ptr+4
).
Создание ptr+5
допустимо, но только в качестве указателя на один конец. Сравнение ptr+5 == &v[1][0]
также не указывается в результате, даже если их двоичные значения будут абсолютно идентичны в каждом компиляторе в каждой основной аппаратной системе.
Если вы хотите пройти дальше по кроличьей норе, то даже в самом C ++ невозможно реализовать std::vector<int>
из-за этих ограничений на наложение указателей. Последний раз я проверял (что было до c ++ 17 , но я не видел резолюции в C ++ 17), стандартный комитет работал над решением этой проблемы, но я не знаю состояния любое такое усилие. (Это меньшая проблема, чем вы думаете, потому что ничто не требует, чтобы std::vector<int>
был реализован в стандартном C ++; он должен просто иметь стандартное поведение. Он может использовать специфичные для компилятора расширения внутри.)