Hallo,
ich mache im Moment kleine Progrämmchen um mich ein wenig in modernem
C++ zu üben.
Dabei habe ich folgendes Lambda getippt, eigentlich nur um zu
bestätigen, dass es nicht geht, es funktioniert aber:
float level; ist ein Member der Klasse, in deren Konstruktor ich obige
Zeile geschrieben habe.
Ich hätte erwartet, dass das ohne this nicht so geht, die Version
funktioniert erwartungsgemäß nicht.
Meine Frage: Was ist der genaue Grund, warum das funktioniert? Soll das
funktionieren, oder ist das „Zufall"?
Vlg
Timm
Ja das soll so funktionieren. Eigentlich muss man für den Zugriff auf
Membervariablen this capturen, wenn man einen Initializer in seinem
Capture nutzt ist das aber wie eine neue Variable. In diesem Fall
vielleicht etwas verwirrend weil du den gleichen Namen benutzt.
Vielleicht findest du
Sebastian V. schrieb:> Ja das soll so funktionieren. Eigentlich muss man für den Zugriff auf> Membervariablen this capturen
... oder einen default-capture verwenden.
Die einzelnen Elemente in der capture-list müssen entweder
- automatische Variablen ( != member-variables),
- this oder
- ein default-capture
sein.
Hallo,
vielen Dank euch!
@Sebastian
ach das mit dem level=level ist nicht das Problem, ist ja ein =
dazwischen, da sind Quelle und Ziel ja eindeutig, das mit den
komplexeren Ausdrücken ist interessant, ich kannte schon die Move
Capture, aber das es soweit geht war mir nicht klar, definitiv nice to
know!
@Wilhelm
Scott Meyers empfiehlt default capture zu vermeiden, da wollte ich mich
erstmal dran halten, zumindest, bis mein Handicap besser ist :-)
Aber mein Thema ist auch an dieser Stelle eher nicht, wie das geht,
sondern warum.
Vielleicht darf ich noch mal nachhaken? Ich glaube, dass mir noch ein
Quentchen zum Verständnis fehlt. Wie gesagt nicht, was die
Funktionalität angeht, ich weiß jetzt, was ich tippen muss, aber der
Hintergrund liegt noch etwas im Dunkel.
Wenn ich das richtig sehe (?) verhält sich die init capture „normal”.
Analog zu: Ich kann ja über eine normale Referenz oder einen Pointer
auch von außen in eine member-Variable schreiben, das ist ja eigentlich
ganz normal.
Aber was ist mit dieser C++11 capture los? Da fehlt mir noch ein
Schritt. Mir ist klar, dass die C++11 capture sich nur auf den lokalen
Scope bezieht und das this als nicht namentlich aufgeführter Parameter
an die member Funktion übergeben wurde, so dass immer wenn ich level
schreibe eigentlich this->level da steht, aber warum kann ein return
level; eine ohne this gültige Referenz liefern, das [&level] verreckt
aber auf halber Strecke?
Ich vermute es gibt einen Satz, der es mir wie Schuppen von den Augen
fallen lässt?
Vielen Dank
Timm
levelSliderComponent_.setCallback([&level=level](float inLevel)
{level=inLevel;});
legt eine neue Variable level an die nichts mit der Membervariable level
zu tun hat.
Hallo,
Guest schrieb:> levelSliderComponent_.setCallback([&level=level](float inLevel)> {level=inLevel;});>> legt eine neue Variable level an die nichts mit der Membervariable level> zu tun hat.
Stimmt das denn? Nichts miteinander zu tun haben heißt doch, nichts
miteinander zu tun haben!
Wenn ich jetzt doch mal Sebastians Version verwende:
[&l=level]
dann kann ich ja über l im Lambda in die member variable level schreiben
und sie auch auslesen, bei meiner Version werde ich bei jedem Aufruf des
lambdas einen anderen Wert für l haben, mehr "mit der Membervariablen zu
tun haben" geht doch kaum?
vlg
Timm
Timm R. schrieb:> mehr "mit der Membervariablen zu> tun haben" geht doch kaum?
Naja gut, es ist eine Referenz auf die Membervariable, aber es ist eben
nicht die Membervariable selbst die du da benutzt. Darum brauchst du
auch kein this capturen. Das initialisieren im Capture ist im Verhalten
fast identisch zu:
Timm R. schrieb:> Scott Meyers empfiehlt default capture zu vermeiden, da wollte ich mich> erstmal dran halten, zumindest, bis mein Handicap besser ist :-)
Ich kann mich an das Kapitel grad nicht komplett erinnern, würde das
aber (ausnahmsweise) nicht direkt unterschreiben. Wenn du anfängst mehr
als eine Variable des Members zu benötigen, ist ein ein [this] capture
geeigneter.
Soweit ich weiß sind Compiler aktuell nicht smart genug um "unnötige"
Referenzen wegzuoptimieren. Das könnte auf einer langsameren und
kleineren Embedded Platform durchaus wehtun... vor allem dann wenn man
die Lambda Funktion irgendwo speichern will, etwa in einem std::function
Objekt. Wenn man nicht aufpasst wird in so einem Fall dann sogar noch
dynamisch Speicher alloziert, weil die ganzen Referenzen nicht ins
Objekt passen (Stichwort "small object optimization").
Hallo Vincent,
Vincent H. schrieb:> Timm R. schrieb:>> Scott Meyers empfiehlt default capture zu vermeiden, da wollte ich mich>> erstmal dran halten, zumindest, bis mein Handicap besser ist :-)>> Ich kann mich an das Kapitel grad nicht komplett erinnern, würde das> aber (ausnahmsweise) nicht direkt unterschreiben. Wenn du anfängst mehr> als eine Variable des Members zu benötigen, ist ein ein [this] capture> geeigneter.
[this] ist doch keine default capture? Wenn ich das richtig verstehe
sind [=] und [&] die default captures modes? Er schreibt "There are two
default capture modes in C++11: by-reference and by-value." Er schreibt,
man solle lieber explicit capture, wie zB [&divisor] verwenden, darunter
hätte ich auch [this] verstanden, denn expliziter geht´s ja nun nicht?
vlg
Timm
Erm, das stimmt natürlich!
Keine Ahnung wie ich grad auf die Idee kam...
Der Rest bezüglich "wenn mehrere Member dann this", ist aber hoffentlich
weniger Topfen. ;)