Стандарт очень тихий, когда речь идет о модели памяти, и не очень четко описывает некоторые термины, которые он использует. Но я думаю, что нашел рабочую аргументацию (которая может быть немного слабой)
Сначала давайте выясним, что является даже частью объекта. [basi c .types] / 4 :
Представление объекта объекта типа T
- это последовательность N
unsigned char
объектов, занятых объектом типа T
, где N
равно sizeof(T)
. Представление значения объекта типа T
представляет собой набор битов, которые участвуют в представлении значения типа T
. Биты в представлении объекта, которые не являются частью представления значения, являются битами заполнения.
Таким образом, представление объекта b0
состоит из sizeof(blub)
unsigned char
объектов, то есть 8 байтов. Биты заполнения являются частью объекта.
Ни один объект не может занимать пространство другого, если он не является вложенным в него [basi c .life] /1.5:
Время жизни объекта o
типа T
заканчивается, когда:
[...]
(1.5) память, которую занимает объект, освобожден или повторно используется объектом, который не вложен в o
([intro.object]).
Таким образом, срок действия b0
закончится, когда память, занятая он будет повторно использован другим объектом, например b1
. Я не проверял это, но я думаю, что стандарт требует, чтобы подобъект живого объекта также был живым (и я не мог представить, как это должно работать по-другому).
Поэтому хранилище, которое b0
занимает , может не использоваться b1
. Я не нашел определения «занимают» в стандарте, но я думаю, что разумная интерпретация будет «частью представления объекта». В представлении описания объекта цитаты используются слова "take up" 1 . Здесь это будет 8 байтов, поэтому bla
нужен как минимум еще один для b1
.
Особенно для подобъектов (так что среди других элементов данных, не входящих в c), также есть условие [intro.object] / 9 (но это было добавлено с C ++ 20, thx @BeeOnRope)
Два объекта с перекрывающимися временами жизни, которые не являются битовыми полями, могут иметь тот же адрес, если один вложен в другой, или если хотя бы один является подобъектом нулевого размера, и они имеют разные типы; в противном случае они имеют разные адреса и занимают непересекающиеся байты хранилища .
(выделение мое). Здесь снова возникает проблема, которая «занимает» не определена, и снова я бы спорят, чтобы взять байты в объекте представления. Обратите внимание, что есть сноска к этому [basi c .memobj] / footnote 29
В соответствии с правилом «как будто» реализация может хранить два объекта по одному и тому же машинному адресу или вообще не хранить объект, если программа не может наблюдать разницу ([intro.execution]).
, что может позволить компилятору прекратить это, если он может доказать, что нет наблюдаемого побочного эффекта. Я думаю, что это довольно сложно для такой фундаментальной вещи, как макет объекта. Возможно, именно поэтому эта оптимизация применяется только тогда, когда пользователь предоставляет информацию о том, что нет причин создавать непересекающиеся объекты, добавляя атрибут [no_unique_address]
.
tl; dr: заполнение может быть частью объекта и членов должны быть непересекающимися.
1 Я не удержался, добавив ссылку, занимающую, может означать заняться: Пересмотренный словарь Вебстера, G. & C , Merriam, 1913 (акцент мой)
Для хранения или заполнения размеров; занять комнату; покрыть или заполнить; как лагерь занимает пять акров земли. Сэр Дж. Гершель.
Какой стандартный обход был бы полным без обхода по словарю?