2014-10-27 11 views
9

Mam 2 sposoby zwracania pustego ciągu znaków z funkcji.Zwracanie pustego ciągu znaków: efektywny sposób w C++

1)

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

2)

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

który z nich jest bardziej wydajny i dlaczego?

+12

Ani. Użyj 'return {};'. –

+2

A jak to się ma do C? – crashmstr

+3

To wchodzi w głąb bezużytecznej mikrooptymalizacji, którą kompilator optymalizuje za pomocą RVO i elizacji kopiowania. – CoryKramer

Odpowiedz

19

Czy niektóre kopanie. Poniżej znajduje się przykładowy program i odpowiedni montaż:

Kod:

#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(); 
} 

Montaż:

__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 

ten został skompilowany z -std=c++11 -O2.

Możesz zobaczyć, że jest znacznie więcej pracy dla instrukcji return ""; i porównywalnie niewiele dla return std::string i return {}; (te dwie są identyczne).

Jak powiedział Frerich Raabe, przekazując puste C_string, nadal trzeba wykonać przetwarzanie, zamiast tylko przydzielać pamięć. Wydaje się, że to nie może być optymalizowane z dala (przynajmniej nie przez GCC)

Więc odpowiedź jest zdecydowanie używać:

return std::string(); 

lub

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

Chociaż chyba wracasz dużo pustych łańcuchów w kluczu krytycznym wydajności (rejestrowanie chyba?), różnica będzie nadal nieistotna.

+0

Może to wymagać aktualizacji od 2017 roku, wszystkie trzy zwroty możliwości dają taki sam wynik, więc nie ma żadnych problemów ze zwrotem "" lub std :: string {} lub {}. Przetestowany na eksploratorze kompilatora dla clang & gcc –

+0

@TomazCanabrava Powinienem był zauważyć wersję gcc w tym czasie ... Jeśli chcesz dostarczyć testowane wersje clang i gcc, zaznaczę to w odpowiedzi. – Baldrickk

+0

@TomazCanabrava faktycznie, kiedy próbuję gcc i clang z powyższym, otrzymuję podobne wyniki (gcc 7.1/clang4.0.0). co ciekawe, Visual Studio (2015) zapewnia wyniki, które są spójne między każdą wersją, ale działa we wszystkich przypadkach. – Baldrickk

3

Ta druga wersja nigdy nie jest wolniejsza od pierwszej. Pierwsza wersja wywołuje konstruktor std::string pobierający ciąg C, który następnie musi najpierw obliczyć długość ciągu. Chociaż jest to szybkie do zrobienia dla pustego łańcucha, z pewnością nie jest to szybsze, niż nie robienie tego w ogóle.

+0

Ponieważ jest to stała, która jest zwracana, czy obliczenie długości nie jest zoptymalizowane przez kompilator? Jeśli nie, to może być? – Baldrickk

+0

@Baldrickk Wywołuje konstruktor argumentu 'std :: string'.Nie sądzę, że istnieje wiele (jeśli w ogóle) kompilatorów, które są na tyle sprytne, aby wywnioskować, że konstruktor argumentów jest odpowiednikiem konstruktora pobierającego zarówno wskaźnik, jak i rozmiar, pod warunkiem, że przekazuje on o jeden mniej niż rozmiar ciągu znaków. dosłowny (który ma końcowe "\ 0"). –

+0

@JamesKanze: niektóre kompilatory optymalizują 'strlen()' na literale łańcuchowym - poprosiłem o dodanie tej funkcji do SparcWorks C++ ponad dekadę temu - nie wiem, czy kiedykolwiek to zrobili - GCC już wtedy to zrobiło. Nadal - nie oczekiwałbym, że implementacja C++ użyje 'strlen' ... nigdy nie wiadomo. –

Powiązane problemy