Considera le seguenti tre structs:
class blub {
int i;
char c;
blub(const blub&) {}
};
class blob {
char s;
blob(const blob&) {}
};
struct bla {
blub b0;
blob b1;
};
Su piattaforme tipiche in cui intsono presenti 4 byte, le dimensioni, gli allineamenti e il riempimento totale 1 sono i seguenti:
struct size alignment padding
-------- ------ ----------- ---------
blub 8 4 3
blob 1 1 0
bla 12 4 6
Non vi è alcuna sovrapposizione tra la memoria dei membri blube blob, anche se la dimensione 1 blobpotrebbe in linea di principio "adattarsi" all'imbottitura di blub.
C ++ 20 introduce l' no_unique_addressattributo, che consente ai membri vuoti adiacenti di condividere lo stesso indirizzo. Inoltre, consente esplicitamente lo scenario sopra descritto di utilizzare il riempimento di un membro per memorizzarne un altro. Da cppreference (sottolineatura mia):
Indica che questo membro di dati non deve necessariamente avere un indirizzo distinto da tutti gli altri membri di dati non statici della sua classe. Ciò significa che se il membro ha un tipo vuoto (ad es. Allocatore senza stato), il compilatore può ottimizzarlo per non occupare spazio, proprio come se fosse una base vuota. Se il membro non è vuoto, è possibile riutilizzare qualsiasi padding di coda per memorizzare altri membri di dati.
In effetti, se usiamo questo attributo su blub b0, la dimensione di blascende a 8, quindi blobè effettivamente memorizzato nel blub come visto su godbolt .
Infine, arriviamo alla mia domanda:
Quale testo negli standard (da C ++ 11 a C ++ 20) impedisce questa sovrapposizione senza no_unique_address, per oggetti che non sono banalmente copiabili?
Devo escludere oggetti banalmente copiabili (TC) da quanto sopra, perché per gli oggetti TC, è consentito passare std::memcpyda un oggetto a un altro, compresi gli oggetti secondari dei membri, e se la memoria fosse sovrapposta si spezzerebbe (perché tutto o parte della memoria poiché il membro adiacente verrebbe sovrascritto) 2 .
1 Calcoliamo l'imbottitura semplicemente come la differenza tra la dimensione della struttura e la dimensione di tutti i suoi componenti, in modo ricorsivo.
2 Questo è il motivo per cui ho definito i costruttori di copie: da rendere blube blobnon banalmente copiabili .