const statisches automatisches Lambda, das bei der Erfassung als Referenz verwendet wird

8

Bei der Verwendung einiger lokaler Lambda-Objekte in einer C ++ 11-Funktion war ich versucht, sie als const static auto lambda = ... zu deklarieren, nur damit der Compiler weiß, dass nur ein std::function -Objekt benötigt wird (und möglicherweise den Aufruf optimieren und / oder inline es), aber ich erkannte, dass das Erfassen von lokalen Werten durch Referenz in diesem Fall zu merkwürdigem Verhalten führt.

Betrachten Sie den folgenden Code:

%Vor%

Dies funktioniert nicht mit mehreren Aufrufen von doSomething() , aber die Mechanik ist nicht klar.

  • Ist foo beim ersten Aufruf gebunden und dann an eine Stapeladresse gebunden, die bei aufeinanderfolgenden Aufrufen ungültig wird?
  • Bin ich gezwungen, in diesem Fall static fallen zu lassen?

Wo ist dieses Verhalten im Standard angegeben? Bedenkt man, dass es eine static Variable ist, wo ist es konstruiert? Faul beim ersten Aufruf von doSomething() (damit der erste Aufruf funktioniert) oder beim Programmstart?

    
Jack 23.06.2015, 10:06
quelle

2 Antworten

12

Eine statische Funktion-Scope-Variable wird "träge" initialisiert, wenn der Kontrollfluss zuerst seine Deklaration erreicht. Dies bedeutet, dass die Erfassung durch Referenz tatsächlich an den foo aktuell auf dem Stapel bindet, und wenn der Aufruf beendet wird, wird diese Bindung schwankend.

Versuchen Sie nicht, dem Compiler zu viel zu helfen; make lambda static sieht wie eine Mikrooptimierung aus, mit sehr schlechten Nebenwirkungen. Es gibt so gut wie keinen Aufwand, um ein Closure-Objekt tatsächlich zu erstellen, und der Compiler kann es einfach inline einfügen, unabhängig davon, ob es static ist oder nicht.

Ganz zu schweigen von der Tatsache, dass Sie bei der Erstellung des std::function -Objekts nicht sparen, auch wenn Sie mit Ihrem Ansatz arbeiten. Der Typ eines Lambda-Ausdrucks ist ein unbenanntes Abschlussobjekt, nicht std::function . Also, auch wenn lambda ist static , das std::function Objekt wird trotzdem in jedem Aufruf erstellt (es sei denn das Ganze ist inline).

    
Angew 23.06.2015, 10:13
quelle
0
  

Dies funktioniert nicht mit mehreren Aufrufen von doSomething() , aber die Mechanik ist nicht klar.

Dies liegt daran, dass foo auf dem Stapel zugeordnet ist. Die genaue Adresse von foo hängt von dem Aufruf-Stack ab, der zum Aufruf von doSomething führte. Mit anderen Worten, die Adresse von foo unterscheidet sich wahrscheinlich zwischen Funktionsaufrufen, es sei denn, der Aufrufstapel ist genau derselbe.

    
Maxim Egorushkin 23.06.2015 10:21
quelle

Tags und Links