2012-07-02 15 views
15

stavo attraversando grandi articoli sul C++ POD, Trivial and Standard Layout classes Una proprietà che non ho ben capito di layout standard è la seguente: -standard layout C++

A standard layout has no base classes of the same type as the first 
    non-static data member 

Quindi quanto segue non sarà un layout standard in quanto ha il primo elemento stesso della classe base

struct NonStandardLayout3 : StandardLayout1 { 
    StandardLayout1 x; // first member cannot be of the same type as base 
}; 

Ma riguarda le prestazioni e proprietà-saggio com'è struct sopra qualsiasi diverso

struct StandardLayout5 : StandardLayout1 { 
    int x; 
    StandardLayout1 y; // can have members of base type if they're not the first 
}; 

che è la correzione di quello sopra questo.

+0

correlati [post] (http://stackoverflow.com/q/7160901/183120). – legends2k

risposta

15

La ragione è che i tipi di layout standard impongono efficacemente l'ottimizzazione della "classe base vuota" in cui le classi di base senza membri di dati non occupano spazio e hanno lo stesso indirizzo del primo membro di dati (se presente) della classe derivata.

Tuttavia, tentare di farlo quando la classe base ha lo stesso tipo del primo membro dati viola il modello di memoria C++ che richiede che gli oggetti distinti dello stesso tipo debbano avere indirizzi distinti.

da ISO/IEC 14882: 2011 1.8 [intro.object]/6:

Due oggetti che non sono di bit campi possono avere lo stesso indirizzo se uno è un oggetto secondario dell'altro, o se almeno uno è un subobject di classe base di dimensione zero e sono di tipi diversi; altrimenti, esse hanno indirizzi distinti

dà mandato efficacemente la classe base vuota, 9.2 [class.mem]/20:

Un puntatore a un oggetto struct standard di layout, opportunamente convertito utilizzando un reinterpret_cast , punta al suo membro iniziale (o se quel membro è un campo di bit, quindi all'unità in cui risiede) e viceversa.

sarebbe impossibile per i seguenti tipi (Type1 e Type2) per essere la layout-compatibili (anche se sarebbero altrimenti classi standard di layout) senza questa restrizione.

struct S1 {}; 
struct S2 {}; 

struct Type1 : S1 { 
    S1 s; 
    int k; 
}; 

struct Type2 : S1 { 
    S2 s; 
    int m; 
}; 
+3

Questo è esattamente ciò che dice anche la nota a piè di pagina per questa regola al §9/7: "[Questa regola] assicura che due sottooggetti che hanno lo stesso tipo di classe e che appartengono allo stesso oggetto derivato non siano allocati allo stesso indirizzo" –

+0

'Type2' era una classe * standard-layout * secondo C++ 14 e continua ad essere una classe * standard-layout * secondo N4606 e [C++ 1z] (http://eel.is/c+ + draft/class # 7), poiché 'S1' non è dello stesso tipo di' S2'. – Belloc