2014-10-27 10 views
9

Ho 2 modi per restituire una stringa vuota da una funzione.Restituire una stringa vuota: modo efficiente in C++

1)

std::string get_string() 
{ 
    return ""; 
} 

2)

std::string get_string() 
{ 
    return std::string(); 
} 

che uno è più efficiente e perché?

+12

Nessuno dei due. Usa 'return {};'. –

+2

E come si riferisce a C? – crashmstr

+3

Questo rientra nel regno della micro-ottimizzazione inutile che il tuo compilatore ottimizzerà usando RVO e copia elision. – CoryKramer

risposta

19

Ha scavato. Di seguito è riportato un programma di esempio e l'assemblea in questione:

Codice:

#include <string> 

std::string get_string1(){ return ""; } 

std::string get_string2(){ return std::string(); } 

std::string get_string3(){ return {}; }   //thanks Kerrek SB 

int main() 
{ 
    get_string1(); 
    get_string2(); 
    get_string3(); 
} 

Assemblea:

__Z11get_string1v: 
LFB737: 
    .cfi_startproc 
    pushl %ebx 
    .cfi_def_cfa_offset 8 
    .cfi_offset 3, -8 
    subl $40, %esp 
    .cfi_def_cfa_offset 48 
    movl 48(%esp), %ebx 
    leal 31(%esp), %eax 
    movl %eax, 8(%esp) 
    movl $LC0, 4(%esp) 
    movl %ebx, (%esp) 
    call __ZNSsC1EPKcRKSaIcE 
    addl $40, %esp 
    .cfi_def_cfa_offset 8 
    movl %ebx, %eax 
    popl %ebx 
    .cfi_restore 3 
    .cfi_def_cfa_offset 4 
    ret $4 
    .cfi_endproc 

__Z11get_string2v: 
LFB738: 
    .cfi_startproc 
    movl 4(%esp), %eax 
    movl $__ZNSs4_Rep20_S_empty_rep_storageE+12, (%eax) 
    ret $4 
    .cfi_endproc 

__Z11get_string3v: 
LFB739: 
    .cfi_startproc 
    movl 4(%esp), %eax 
    movl $__ZNSs4_Rep20_S_empty_rep_storageE+12, (%eax) 
    ret $4 
    .cfi_endproc 

Questo è stato compilato con -std=c++11 -O2.

Si può notare che c'è molto più lavoro per la dichiarazione return ""; e relativamente piccola per return std::string e return {}; (questi due sono identici).

Come ha detto Frerich Raabe, quando si passa uno C_string vuoto, è ancora necessario eseguire l'elaborazione su di esso, invece di allocare solo memoria. Sembra che questo non può essere ottimizzata di distanza (almeno non da GCC)

Quindi la risposta è quella di utilizzare definitivamente:

return std::string(); 

o

return {}; //(c++11) 

Anche se a meno che non stanno tornando molto di stringhe vuote nel codice critico delle prestazioni (registrazione suppongo?), la differenza sta per essere ancora insignificante.

+0

Forse questo ha bisogno di un aggiornamento a partire dal 2017 tutte e tre le restituzioni restituiscono lo stesso risultato asm quindi non ci sono problemi nel restituire un "" o uno std :: string {} o {}. Testato su compiler explorer per clang & gcc –

+0

@TomazCanabrava Avrei dovuto notare la versione di gcc al momento ... Se vuoi fornire le versioni clang e gcc che hai provato, lo noterò nella risposta. – Baldrickk

+0

@TomazCanabrava in realtà, quando provo gcc e clang con quanto sopra, ottengo risultati simili (gcc 7.1/clang4.0.0). In modo abbastanza interessante, Visual Studio (2015) fornisce risultati coerenti tra ciascuna versione, ma in tutti i casi funziona di più. – Baldrickk

3

Quest'ultima versione non è mai più lenta della prima. La prima versione chiama il costruttore std::string prendendo una stringa C, che quindi deve calcolare prima la lunghezza della stringa. Anche se è veloce da fare per una stringa vuota, non è certamente più veloce di non farlo affatto.

+0

Poiché è una costante che viene restituita, il calcolo della lunghezza non è ottimizzato dal compilatore? Se no, potrebbe essere? – Baldrickk

+0

@Baldrickk Sta chiamando il costruttore di un argomento di 'std :: string'.Non penso che ci siano molti (se nessuno) compilatori che sono abbastanza intelligenti da dedurre che il costruttore di un argomento è l'equivalente del costruttore che prende sia un puntatore sia una dimensione, a condizione che passi meno della dimensione della stringa letterale (che ha un trailing ''\ 0''). –

+0

@JamesKanze: alcuni compilatori ottimizzano 'strlen()' su una stringa letterale - ho richiesto che la funzione fosse aggiunta a SparcWorks C++ più di dieci anni fa - non so se l'hanno mai fatto - GCC lo ha già fatto in passato. Tuttavia, non mi aspetterei che un'implementazione in C++ utilizzi 'strlen' ... non si sa mai. –

Problemi correlati