Рассмотрим следующие три struct
с:
class blub {
int i;
char c;
blub(const blub&) {}
};
class blob {
char s;
blob(const blob&) {}
};
struct bla {
blub b0;
blob b1;
};
На типовых платформах, где int
4 байта, размеры, выравнивания и общее заполнение 1 следующие:
struct size alignment padding
-------- ------ ----------- ---------
blub 8 4 3
blob 1 1 0
bla 12 4 6
Не существует дублирования между хранением элементов blub
и blob
, даже если размер 1 blob
в принципе может «вписаться» в отступы blub
.
C ++ 20 вводит no_unique_address
атрибут, который позволяет соседним пустым элементам использовать один и тот же адрес. Это также явно позволяет описанный выше сценарий использования заполнения одного элемента для хранения другого. Из контекста (акцент мой):
Указывает, что этот член данных не должен иметь адрес, отличный от всех других нестатических членов данных своего класса. Это означает, что если элемент имеет пустой тип (например, Allocator без сохранения состояния), компилятор может оптимизировать его, чтобы он не занимал места, как если бы он был пустой базой. Если элемент не пустой, любой хвостовой отступ в нем также может быть повторно использован для хранения других элементов данных.
В самом деле, если мы используем этот атрибут blub b0
, размер bla
падает до 8
, так что blob
он действительно сохраняется в том blub
виде, в каком это видно на Годболте .
Наконец, мы добрались до моего вопроса:
Какой текст в стандартах (C ++ 11 - C ++ 20) предотвращает это перекрытие no_unique_address
, для объектов, которые нетривиально копируются?
Мне нужно исключить тривиально копируемые (TC) объекты из вышеперечисленного, потому что для объектов TC разрешено переходить std::memcpy
от одного объекта к другому, включая дочерние подобъекты, и если хранилище было перекрыто, это сломалось бы (потому что все или часть хранилища для соседнего члена будет перезаписано) 2 .
1 Мы вычисляем заполнение просто как разницу между размером структуры и размером всех составляющих ее элементов, рекурсивно.
2 Вот почему я определил конструкторы копирования: сделать blub
и blob
не просто копировать .