2015-05-13 10 views
6

Supponiamo che io sono un std::tuple:GCC ottimizza std :: tie usato solo per la leggibilità?

std::tuple<int,int,int,int> t = {1,2,3,4}; 

e voglio usare std::tie solo per scopo la leggibilità del genere:

int a, b, c, d; // in real context these names would be meaningful 
std::tie(a, b, c, d) = t; 

vs. usando solo t.get<int>(0), ecc

Sarebbe un GCC ottimizzare l'utilizzo della memoria di questa tupla o allocare spazio aggiuntivo per le variabili a, b, c, d?

+4

perché non provarlo? (btw, probabilmente lo sarebbe.) –

+0

correlati [Le variabili temporanee rallentano il mio programma?] (http://stackoverflow.com/q/26949569/1708801) –

+1

Controlla [Godbolt] (https: //gcc.godbolt. org /). Risposta breve: per un semplice esempio, sì. Sommando gli elementi in una tupla tramite 'tie()' o 'get ()' produce un assemblaggio identico. – Barry

risposta

7

In questo caso non vedo alcun motivo per cui, con il as-if rule, il compilatore deve solo emulare il comportamento osservabile del programma. Un rapido esperimento using godbolt:

#include <tuple> 
#include <cstdio> 

void func(int x1, int x2,int x3, int x4) 
{ 
    std::tuple<int,int,int,int> t{x1,x2,x3,x4}; 

    int a, b, c, d; // in real context these names would be meaningful 
    std::tie(a, b, c, d) = t; 

    printf("%d %d %d %d\n", a, b, c, d) ; 
} 

dimostra che gcc effettivamente ottimizzare via:

func(int, int, int, int): 
    movl %ecx, %r8d 
    xorl %eax, %eax 
    movl %edx, %ecx 
    movl %esi, %edx 
    movl %edi, %esi 
    movl $.LC0, %edi 
    jmp printf 

D'altra parte, se è stato utilizzato un indirizzo di t e stampato fuori, ora abbiamo comportamento osservabile che si basa su t esistente (see it live):

printf("%p\n", static_cast<void*>(&t)); 

e possiamo vedere che gcc non ottimizza via il t:

movl %esi, 12(%rsp) 
leaq 16(%rsp), %rsi 
movd 12(%rsp), %xmm1 
movl %edi, 12(%rsp) 
movl $.LC0, %edi 
movd 12(%rsp), %xmm2 
movl %ecx, 12(%rsp) 
movd 12(%rsp), %xmm0 
movl %edx, 12(%rsp) 
movd 12(%rsp), %xmm3 
punpckldq %xmm2, %xmm1 
punpckldq %xmm3, %xmm0 
punpcklqdq %xmm1, %xmm0 

Alla fine della giornata è necessario guardare a ciò che il compilatore genera e creare il profilo del codice, nei casi più complicati può sorprendere. Solo perché il compilatore è autorizzato a fare certe ottimizzazioni non significa che lo farà. Ho esaminato casi più complicati in cui il compilatore non fa ciò che mi aspetterei con std::tuple. Godbolt è uno strumento molto utile qui, non posso contare quante supposizioni di ottimizzazioni ho usato che sono state capovolte collegando semplici esempi in Godbolt.

Nota, in genere utilizzo printf in questi esempi perché gli iostreams generano molto codice che interferisce con l'esempio.

+1

Non ti rendi conto che potresti condividere esempi di Godbolt. Ecco [il mio] (https://goo.gl/ilaeZg). – Barry

+1

@Barry felice hai imparato qualcosa di nuovo, sento che è una caratteristica essenziale, non essere in grado di condividere esempi del genere renderebbe molto meno utile.Questo è ciò che è fantastico di SO, imparando sempre qualcosa di nuovo. –

+0

Ritengo che l'informazione più importante nella tua risposta sia l'ultimo paragrafo. – bolov