Rozważ następujące trzy structs:
class blub {
int i;
char c;
blub(const blub&) {}
};
class blob {
char s;
blob(const blob&) {}
};
struct bla {
blub b0;
blob b1;
};
Na typowych platformach, na których intsą 4 bajty, rozmiary, wyrównania i całkowite wypełnienie 1 są następujące:
struct size alignment padding
-------- ------ ----------- ---------
blub 8 4 3
blob 1 1 0
bla 12 4 6
Przechowywanie elementów blubi blobelementów nie zachodzi na siebie , mimo że rozmiar 1 blobmógłby w zasadzie „pasować” do wypełnienia blub.
C ++ 20 wprowadza no_unique_addressatrybut, który pozwala sąsiednim pustym członkom na dzielenie tego samego adresu. Pozwala to również wyraźnie na opisany powyżej scenariusz użycia wypełnienia jednego elementu do przechowywania innego. Z preferencji (moje podkreślenie):
Wskazuje, że ten członek danych nie musi mieć adresu odrębnego od wszystkich innych niestatycznych członków danych swojej klasy. Oznacza to, że jeśli element członkowski ma pusty typ (np. Bezstanowy alokator), kompilator może go zoptymalizować, aby nie zajmował miejsca, tak jakby był pustą bazą. Jeśli element członkowski nie jest pusty, wszelkie wypełnienia ogona mogą zostać ponownie wykorzystane do przechowywania innych elementów danych.
Rzeczywiście, jeśli użyjemy tego atrybutu blub b0, wielkość blakropli spadnie do 8, więc blobrzeczywiście jest on przechowywany w blub postaci widocznej na godbolt .
Wreszcie dochodzimy do mojego pytania:
Jaki tekst w standardach (od C ++ 11 do C ++ 20) zapobiega temu nakładaniu się no_unique_address, w przypadku obiektów, których nie można w prosty sposób skopiować?
Muszę wykluczyć z powyższego obiekty trywialnie kopiowalne (TC), ponieważ w przypadku obiektów TC dozwolone jest przechodzenie std::memcpyz jednego obiektu do drugiego, w tym podobiektów składowych, a jeśli magazyn byłby nałożony, to by się zepsuło (ponieważ całość lub część magazynu ponieważ sąsiedni członek zostanie zastąpiony) 2 .
1 Obliczamy wypełnienie po prostu rekurencyjnie jako różnicę między rozmiarem struktury a rozmiarem wszystkich jej elementów składowych.
2 Jest to dlaczego mam konstruktory kopia zdefiniowane: zrobić blubi blobnie trywialnie copyable .