2010-07-10 18 views
25

Gibt es einen Overhead bei der Verwendung von Lambda-Ausdrücken in C++ 0x (unter VS2010)?
Ich weiß, dass die Verwendung von Funktion Objekte Aufwand verursacht, aber ich beziehe mich auf Ausdrücke, die zum Beispiel an STL-Algorithmen übergeben werden. Optimiert der Compiler den Ausdruck und entfernt so scheinbar einen Funktionsaufruf? Ich fing an, Lambda-Ausdrücke wirklich zu mögen, aber ich bin etwas besorgt über die Geschwindigkeitsstrafe.C++ 0x Lambda-Overhead

Vielen Dank im Voraus!

+7

Warum verwenden Sie wirklich Funktionsobjekte (Funktoren) Overhead? Sie können auch optimiert werden! Die einzige Möglichkeit, dies zu wissen, besteht darin, mit aktivierten vollständigen Optimierungen zu erstellen und dann die Assembly zu betrachten. – EFraim

+0

Wenn ich Funktionsobjekt sagte, bezog ich mich auf etwas wie boost :: function, mein Fehler. Ich weiß, dass klassische Funktionsobjekte inline sein können, und ich wollte wissen, ob dies auch mit Lambda passiert. –

+0

ah ok, die haben etwas Overhead. Aber Lambdas nicht (es sei denn, Sie wickeln sie in ein "std :: function" -Objekt ein (müssen nicht Boost verwenden, da das in den 0x-Standard übernommen wurde) – jalf

Antwort

43

Sie "wissen", dass Funktionsobjekte Overhead verursachen? Vielleicht sollten Sie Ihre Fakten überprüfen. :)

Es gibt normalerweise keinen Aufwand für die Verwendung eines STL-Algorithmus mit einem Funktionsobjekt im Vergleich zu einer handgewalzten Schleife. Ein naiver Compiler muss operator() auf dem Funktor wiederholt aufrufen, aber das ist trivial zu Inline und so ist der Overhead tatsächlich Null.

Ein Lambda-Ausdruck ist nichts anderes als syntaktischer Zucker für ein Funktionsobjekt. Der Code wird vom Compiler in ein Funktionsobjekt umgewandelt, also hat er auch keinen Overhead.

+4

Empirisch ist das falsch. Das Hinzufügen vieler Instanzen von 'std :: functions' erhöht die Größe der ausführbaren Datei, zumindest in VS2010. Ich habe gerade diesen Test durchgeführt. – shoosh

+8

@shoosh: Also? Das Hinzufügen vieler Instanziierungen von 'std: string' verursacht ebenfalls eine Menge Overhead. Aber das war nicht die Frage oder meine Antwort. Es ging um Funktionsobjekte und Lambdas. 'std :: function' ist weder. – jalf

+8

nur zu erarbeiten, 'std :: function' ist eine Wrapper-Klasse, eine Abstraktion über alle aufrufbaren Objekte, ob Funktionszeiger oder Funktoren. Und es ist nicht kostenlos zu benutzen. Aber wenn Sie den Wrapper vermeiden und nur einen Funktor oder ein Lambda direkt verwenden, gibt es keinen Overhead – jalf

18

Unter der Haube

void f(char delim) 
{ 
    std::for_each(seq.begin() 
       , seq.end() 
       , [=](const T& obj){std::cout << obj << delim;}); 
} 

übersetzt etwa in

class __local_class_name { 
    char __delim; 
public: 
    __local_class_name(char delim) : __delim(delim) {} 
    void operator()(const T& obj) {std::cout << obj << __delim;} 
}; 

void f(char delim) 
{ 
    std::for_each(seq.begin() 
       , seq.end() 
       , __local_class_name(delim)); 
} 

Wie bei allen Funktionsobjekte, die Overhead sehr minimal ist, da der Anruf leicht inlined werden kann.

+2

Bitte beachten Sie, dass 'delim' explizit erfasst werden muss. – Dario

+4

Er tut; '[=]' zeigt an, dass alle lokalen Objekte durch Wert erfasst werden sollen. –

+1

@Dennis: Nur jalf hat das '=' hinzugefügt, also hatte @Dario Recht. ': (' @jalf: Danke. Meine Entschuldigung ist dass ich noch nicht die Zeit hatte, damit zu spielen, also ist alles vom Hörensagen getippt. – sbi