2014-11-04 9 views
6

Ich versuche so einfachen Code:Warum kann der Compiler std :: string concat nicht optimieren?

#include <cstdio> 
#include <string> 

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

ich den Compiler (gcc 4.8.2/Klirren 3.5.0) optimieren solchen Code zu

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

Aber ich kann nicht ein solches Ergebnis erwarten, ich versuchen verschiedene Optionen wie "-Ofast", "-flto", "-static-libstdC++", aber immer in Disassembler Ausgang drei Funktionen siehe nennen:

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

Der erste Anruf ist zu std :: basic_string, std :: allocator> :: basic_string (Zeichen const *, std :: allocator const &).

So sind alle Compiler herum, die solchen Code zu puts ("ab") optimieren können; oder zumindest "std :: string s (" ab ");"?

Und wenn es keinen solchen Compiler gibt, was macht solche Optimierung schwierig zu implementieren?

Aktualisieren Über die reale Verwendung. Ich sehe/sah viele Orte in echten Code mit einem solchen Muster:

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

Und wenn Leistung wichtig ist, ist es natürlich möglich solchen Code in optimaler Art und Weise neu zu schreiben.

Aber moderne Compiler machen großartige Arbeit, um den Code zu optimieren. Und gcc, zum Beispiel haben __builtin Funktionen für malloc/free/strcpy/strcat und so weiter. Und wenn std :: basic_string von libstdC++ aus gcc diese Funktionen (malloc, free, strcpy, strcat) für einen Teil der Implementierung verwendet, warum nicht das Ergebnis der Verwendung der Funktionen vorhersagen und eine Antwort geben.

+0

Da C++ - Klassenkonstruktoren und -Operatoren Funktionen sind, sind sie nicht algebraisch, daher ist es schwierig, algebraische Optimierungen zu erkennen. – didierc

+1

Sie haben nicht gesagt, warum Sie das tun wollen, aber würde 'const std :: string s = "a" "b";' Passen Sie Ihre Bedürfnisse? Zeichenfolgenliterale werden automatisch eingefügt, wenn sie nebeneinander geschrieben werden. –

+0

Um klar zu sein, ermöglicht der C++ - Standard die Optimierung des Programms für 'puts (" ab "); oder gleichwertig. Compiler tun es aber nicht. Ich nehme an, du müsstest einen Compiler-Entwickler fragen, aber vielleicht gehört ein Teil dazu, die Wünsche des Programmierers zu respektieren. Wenn sie letztlich der * als-ob * -Regel folgen würden, gäbe es viele Beschwerden; z.B. Einen Systemaufruf zu machen, um etwas auf den Bildschirm zu schreiben oder zu schlafen, hat kein beobachtbares Verhalten gemäß der Definition in C++ 14. –

Antwort

7

std::string beinhaltet die dynamische Zuweisung von Speicher und in den meisten Fällen eine extrem komplexe Implementierung und kann daher nicht auf Kompilierzeitsemantik reduziert werden, egal wie gut der Compiler konstant zu einer Fine Art zusammenfaltet.

Allerdings: Wenn Ihr string tatsächlich so erklärt wird, warum haben Sie nicht ein char Array an erster Stelle verwendet, aber string gewählt? Wenn Sie mit einigen Zeichenfolgen arbeiten müssen, um andere zu erzeugen, gibt es immer noch Tools, die diesen Job mit char Arrays ausführen können, besonders seit C++ 11 variadic Vorlagen eingeführt und constexpr. Eine zukünftige Version von C++ wird hoffentlich auch einführen, um das zu erleichtern.

+0

Wäre es möglich, C++ 14 Features zu verwenden, um einen constexpr std :: string :: operator + zu haben und die Anfrage von OP zu implementieren? – liori

+0

@liori sollte ich mir denken, da 'string_literal' auf C++ 14 basiert. – Columbo

+1

Es gibt auch das komplizierende Problem, dass GCCs 'std :: string' immer noch Copy-on-Write ist. –

Verwandte Themen