2016-03-26 19 views
6

Durante la lettura di this sono rimasto sbalordito da ciò che un determinato livello di metaprogrammazione può fare per il layout della classe. Devo ammettere che non comprendere appieno qual è la disposizione ottimale proposto, se dovessi indicare quale ho capito che sarebbe questo:Le implementazioni di tuple hanno un layout ottimizzato?

ordinamento membro della classe scendendo allineamento cioè del tipo con la massima alignof risultato va prima ecc

Sentiti libero di correggermi se ho ottenuto questo torto (se si ha una breve spiegazione del motivo per cui questo accade, sarebbe ancora meglio, non ho potuto copiare incollare grandi blocchi di motivazioni nella mia interrogazione) , ma la mia domanda è su un altro argomento:

Qual è l'implementazione di libreria di std::tuple con una tale ottimizzazione del layout?

In caso contrario, ci sono tipi di dati algebrici standard che lo fanno, c'è un altro modo per fare questo per la mia classe oltre alla scrittura di un tale macchinario?

risposta

9

Nessuna implementazione di libreria Sono a conoscenza dell'ottimizzazione del layout per l'allineamento. È possibile utilizzare un programma come questo per ispezionare un layout tuple:

#include <iostream> 
#include <tuple> 

struct empty {}; 

int 
main() 
{ 
    using T = std::tuple<double, int, empty, short, long>; 
    T t{}; 
    std::cout << &t << '\n'; 
    std::cout << &std::get<0>(t) << '\n'; 
    std::cout << &std::get<1>(t) << '\n'; 
    std::cout << &std::get<2>(t) << '\n'; 
    std::cout << &std::get<3>(t) << '\n'; 
    std::cout << &std::get<4>(t) << '\n'; 
    std::cout << &t+1 << '\n'; 
    std::cout << sizeof(T) << '\n'; 
} 

libC++ memorizza elementi ordine di dichiarazione, e ottimizza lo spazio via per membri vuoti. I membri vuoti vengono deviati verso la parte anteriore. Esempio di output:

0x7fff5ccf39f8 
0x7fff5ccf39f8 
0x7fff5ccf3a00 
0x7fff5ccf39f8 
0x7fff5ccf3a04 
0x7fff5ccf3a08 
0x7fff5ccf3a10 
24 

memorizza libstdC++ elementi in ordine inverso di dichiarazione e ottimizza lo spazio via per membri vuoti. I membri vuoti vengono deviati verso la parte anteriore. Esempio di output: memorizza

0x7ffe4fc5b2a0 
0x7ffe4fc5b2b0 
0x7ffe4fc5b2ac 
0x7ffe4fc5b2a0 
0x7ffe4fc5b2a8 
0x7ffe4fc5b2a0 
0x7ffe4fc5b2b8 
24 

VS-2015 elementi in ordine inverso di dichiarazione e non ottimizza lo spazio per via membri vuoti. Esempio di output:

0306FEF4 
0306FF04 
0306FF00 
0306FEFC 
0306FEF8 
0306FEF4 
0306FF0C 
24 

In questo esempio vediamo che ottimizzando lo spazio via per il membro vuoto non ha comprato nulla in quanto si inserisce in una zona di imbottitura in ogni caso.

Non ci sono strutture che automatizzano il compito di ridurre il riempimento nello standard.

+0

Potresti per favore approfondire perché l'ordinamento in base all'allineamento discendente sarebbe un layout ottimale? –

+0

@LorahAttkins: questa è un'euristica che spesso funziona. Presume che la classe stessa di solito sia massimamente allineata, quindi mettere i membri massimamente allineati per primi non garantisce byte di riempimento tra i membri massimamente allineati. Quindi passa ai tuoi prossimi membri di allineamento più grandi e manterrà la stessa logica. Quando si esauriscono i membri, di solito si aggiunge un padding aggiunto afterwords per arrotondare la dimensione di (your_class) a un multiplo dell'allineamento di classe. Quindi a volte il trucco ordine per allineamento ti salverà byte, ea volte no. È un buon strumento da avere nella casella degli strumenti. –

+0

Dovrei aver aggiunto al mio commento sopra: La dimensione di ogni tipo è un multiplo dell'allineamento per quel tipo. Per esempio non esiste un tipo con un allineamento di 16 byte e una dimensione di 15 o 17. La sua dimensione di 16, o 32, o 48, ecc. Ciò implica che sia '& a' * che *' & a + 1' sono puntatori con allineamento almeno grande come 'alignof (a)'. –