it-swarm.com.de

Warum kann ich diese Referenz ('& this') in Lambda nicht erfassen?

Ich verstehe die korrekte Methode zum Erfassen von this (zum Ändern von Objekteigenschaften) in einem Lambda wie folgt:

auto f = [this] () { /* ... */ };

Aber ich bin neugierig auf die folgende Besonderheit, die ich gesehen habe:

class C {
    public:
        void foo() {
            // auto f = [] () { // this not captured
            auto f = [&] () { // why does this work?
            // auto f = [&this] () { // Expected ',' before 'this'
            // auto f = [this] () { // works as expected
                x = 5;
            };
            f();
        }

    private:
        int x;
};

Die Kuriosität, die mich verwirrt (und die ich gerne beantwortet hätte), ist, warum Folgendes funktioniert:

auto f = [&] () { /* ... */ }; // capture everything by reference

Und warum ich this nicht explizit als Referenz erfassen kann:

auto f = [&this] () { /* ... */ }; // a compiler error as seen above.
72
Anthony Sottile

Der Grund, warum [&this] nicht funktioniert, ist ein Syntaxfehler. Jeder durch Kommas getrennte Parameter in lambda-introducer ist ein capture:

capture:
    identifier
    & identifier
    this

Sie können sehen, dass &this syntaktisch nicht zulässig ist. Der Grund, warum dies nicht zulässig ist, ist, dass Sie this niemals als Referenz erfassen möchten, da es sich um einen kleinen konstanten Zeiger handelt. Sie möchten es immer nur als Wert übergeben - daher unterstützt die Sprache das Erfassen von this als Referenz einfach nicht.

Um this explizit zu erfassen, können Sie [this] als lambda-introducer verwenden.

Der erste capture kann ein capture-default sein.

capture-default:
    &
    =

Dies bedeutet, dass automatisch erfasst wird, was auch immer ich verwende, anhand des Verweises (&) oder des Wertes (=) - jedoch ist die Behandlung von this eine Besonderheit - in beiden Fällen wird sie erfasst von Wert aus den zuvor angegebenen Gründen (auch bei einer Standarderfassung von &, was normalerweise die Erfassung durch Verweis bedeutet).

5.1.2.7/8:

Zum Nachschlagen von Namen (3.4), Bestimmen von Typ und Wert von this (9.3.2) und Umwandeln von ID-Ausdrücken, die sich auf nicht statische Klassenmitglieder beziehen, in Klassenmitgliedszugriffsausdrücke mit (*this) (9.3.1) wird die zusammengesetzte Aussage [OF THE LAMBDA] im Kontext des Lambda-Ausdrucks betrachtet.

Das Lambda verhält sich also so, als ob es Teil der einschließenden Elementfunktion wäre, wenn Elementnamen verwendet werden (wie in Ihrem Beispiel die Verwendung des Namens x), sodass "implizite Verwendungen" von this genau wie eine Member-Funktion.

Wenn eine Lambda-Erfassung einen Erfassungsstandard enthält, der & lautet, darf & nicht vor den Bezeichnern in der Lambda-Erfassung stehen. Wenn eine Lambda-Erfassung einen Erfassungsstandard enthält, der = ist, darf die Lambda-Erfassung this nicht enthalten, und jeder Kennung, die sie enthält, muss & vorangestellt sein. Ein Bezeichner oder this darf in einer Lambda-Aufnahme nur einmal vorkommen.

Sie können also [this], [&], [=] oder [&,this] als lambda-introducer verwenden, um den Zeiger this nach Wert zu erfassen.

Jedoch sind [&this] und [=, this] schlecht geformt. Im letzten Fall warnt gcc verzeihend für [=,this], dass explicit by-copy capture of ‘this’ redundant with by-copy capture default und nicht für Fehler.

99
Andrew Tomazos

Da Standard kein &this In Captures-Listen hat:

N4713 8.4.5.2 Captures:

lambda-capture:
    capture-default
    capture-list
    capture-default, capture-list

capture-default:
    &
    =
capture-list:
    capture...opt
    capture-list, capture...opt
capture:
    simple-capture
    init-capture
simple-capture:
    identifier
    &identifier
    this
    * this
init-capture:
    identifier initializer
    &identifier initializer
  1. Für die Lambda-Erfassung verweist ein Ausdruck möglicherweise auf lokale Entitäten wie folgt:

    7.3 Ein this-Ausdruck verweist möglicherweise auf * this.

Standardgarantien this und *this Sind gültig und &this Ist ungültig. Das Erfassen von this bedeutet auch das Erfassen von *this (Was ein Wert ist, das Objekt selbst) als Referenz, anstatt das Erfassen von this pointer nach Wert!

4
陳 力