2014-11-04 13 views
6

cerco tale codice semplice:Perché il compilatore non può ottimizzare std :: string concat?

#include <cstdio> 
#include <string> 

int main() 
{ 
    const std::string s = std::string("a") + "b"; 
    puts(s.c_str()); 
    return 0; 
} 

Mi aspetto che il compilatore (gcc 4.8.2/clang 3.5.0) ottimizzare tale codice per

int main() 
{ 
    puts("ab"); 
    return 0; 
} 

ma non riesco a ottenere tale risultato, provare diverse opzioni come "-Ofast", "-flto", "-static-libstdC++", ma vede sempre in uscita disassembler tre funzioni di chiamata:

... 
callq 0x4017e0 <_ZNSsC2EPKcRKSaIcE> 
... 
callq 0x401690 <_ZNSs6appendEPKc> 
... 
callq 0x401490 <_ZNSs4_Rep10_M_disposeERKSaIcE> 

La prima è chiamata a std :: basic_string, std :: allocator> :: basic_string (char const *, std :: allocator const &).

Quindi ci sono tutti i compilatori in giro, che possono optare per un codice simile a puts ("ab"); o almeno a "std :: string s (" ab ");"?

E se non ci sono tali compilatori, cosa rende difficile l'implementazione di tale ottimizzazione?

Aggiornamento Informazioni sull'utilizzo del mondo reale. Vedo/visto molti posti nel codice vero e proprio con tale modello:

std::string s = std::string(string_const1) + string_const2 + string_variable + string_const3; 

E se le prestazioni sono importante, naturalmente, è possibile riscrivere tale codice in modo più ottimale.

Ma i compilatori moderni fanno grandi lavori per ottimizzare il codice. E gcc, ad esempio, ha funzioni __builtin per malloc/free/strcpy/strcat e così via. E se std :: basic_string da libstdC++ da gcc usa queste funzioni (malloc, free, strcpy, strcat) per una parte dell'implementazione, perché non prevedere il risultato dell'uso delle funzioni e dare una risposta.

+0

Poiché i costruttori e gli operatori di classe C++ sono funzioni, non sono algebrici, quindi è difficile individuare le ottimizzazioni algebriche. – didierc

+1

Non hai detto perché vuoi farlo, ma dovresti 'const std :: string s = "a" "b";' adatti alle tue esigenze? I letterali stringa si incollano automaticamente una volta scritti l'uno accanto all'altro. –

+0

Per essere chiari, lo standard C++ consente di ottimizzare il programma a 'puts (" ab ");' o equivalente. Ma i compilatori non lo fanno. Immagino che dovresti chiedere a uno sviluppatore di compilatori, ma forse parte di esso ha a che fare con il rispetto dei desideri del programmatore. Se seguissero la regola * as-if * alla fine, ci sarebbero state molte lamentele; per esempio. fare una chiamata di sistema per scrivere qualcosa sullo schermo, o fare un sonno, non ha alcun comportamento osservabile secondo la definizione in C++ 14. –

risposta

7

std::string implica l'allocazione dinamica dello storage e, nella maggior parte dei casi, un'implementazione estremamente complessa e non può quindi essere ridotta alla semantica in fase di compilazione, indipendentemente dal fatto che il compilatore si sia piegato costantemente a un'arte.

Tuttavia: se il tuo string viene effettivamente dichiarato in questo modo, perché non hai utilizzato un array char in primo luogo ma hai scelto string? Se è necessario lavorare con alcune stringhe per produrne altre, ci sono ancora strumenti che possono fare quel lavoro con gli array char, specialmente dal momento che C++ 11 ha introdotto modelli variadici e constexpr. Speriamo che una versione futura di C++ introduca anche std::string_literal per facilitare ulteriormente questo.

+0

Sarebbe possibile utilizzare le funzionalità di C++ 14 per avere un constexpr std :: string :: operator + e implementare la richiesta dell'OP? – liori

+0

@liori Lo dovrei pensare dato che 'string_literal' è basato su C++ 14. – Columbo

+1

C'è anche il problema complicato che 'std :: string' di GCC è ancora copy-on-write. –

Problemi correlati