Warum wird C++11 lambda-Ausdruck benötigen "veränderlich" keyword " capture-by-Wert, per default?
Kurzes Beispiel:
#include <iostream>
int main()
{
int n;
[&](){n = 10;}(); //OK
[=]() mutable {n = 20;}(); //OK
//[=](){n = 10;}(); //Error: a by-value capture cannot be modified in a non-mutable lambda
std::cout << n << "\n"; //"10"
}
Die Frage: Warum brauchen wir die mutable
keyword? Es ist ganz anders als die traditionellen parameter der übergabe an benannten Funktionen. Was ist die Logik hinter?
War ich unter dem Eindruck, dass der ganze Sinn der capture-by-value ist, um dem Benutzer zu ermöglichen, ändern Sie den temporären -- sonst bin ich fast immer besser mit capture-by-reference, nicht wahr?
Jede Erleuchtung?
(Ich bin mit MSVC2010 durch die Art und Weise. AFAIK sollte dies standard sein)
Gute Frage; obwohl ich bin froh, dass etwas ist schließlich
Keine Antwort, aber ich denke, das ist eine sinnvolle Sache: wenn Sie etwas von Wert, Sie sollte nicht verändert werden, es ist nur zu sparen Sie 1 Kopie auf eine lokale variable. Zumindest werden Sie nicht den Fehler machen, zu ändern n durch ersetzen = mit &.
Nicht sicher, es ist gut, wenn alles andere nicht
Szelei: Nicht zu starten ein argument, aber IMHO das Konzept "einfach zu lernen" hat keinen Platz in der C++ - Sprache, vor allem in der modernen Tage. Sowieso 😛
"der ganze Sinn der capture-Wert wird, um dem Benutzer zu ermöglichen, ändern Sie den temporären" - Nein, der ganze Punkt ist, dass die lambda-Mai gültig bleiben über die Laufzeit eines aufgenommenen Variablen. Wenn C++ lambdas hatte nur capture-by-ref würde, wäre Sie unbrauchbar ist, viel zu viele Szenarien.
const
standardmäßig!Keine Antwort, aber ich denke, das ist eine sinnvolle Sache: wenn Sie etwas von Wert, Sie sollte nicht verändert werden, es ist nur zu sparen Sie 1 Kopie auf eine lokale variable. Zumindest werden Sie nicht den Fehler machen, zu ändern n durch ersetzen = mit &.
Nicht sicher, es ist gut, wenn alles andere nicht
const
standardmäßig.Szelei: Nicht zu starten ein argument, aber IMHO das Konzept "einfach zu lernen" hat keinen Platz in der C++ - Sprache, vor allem in der modernen Tage. Sowieso 😛
"der ganze Sinn der capture-Wert wird, um dem Benutzer zu ermöglichen, ändern Sie den temporären" - Nein, der ganze Punkt ist, dass die lambda-Mai gültig bleiben über die Laufzeit eines aufgenommenen Variablen. Wenn C++ lambdas hatte nur capture-by-ref würde, wäre Sie unbrauchbar ist, viel zu viele Szenarien.
InformationsquelleAutor kizzx2 | 2011-03-31
Du musst angemeldet sein, um einen Kommentar abzugeben.
Bedarf es
mutable
da standardmäßig ein function-Objekt erzeugen soll, das gleiche Ergebnis jedes mal, wenn es aufgerufen wird. Das ist der Unterschied zwischen einer Objekt-orientierten-Funktion und eine Funktion mit einer globalen Variablen, effektiv.void f(const std::function<int(int)> g)
. Wie wird mir garantiert, dassg
ist eigentlich referentiell transparent?g
's Anbieter verwendetmutable
sowieso. So kann ich nicht wissen. Auf der anderen Seite, wenn der Standard ist nichtconst
, und die Menschen müssen hinzufügenconst
stattmutable
Funktion der Objekte, die der compiler kann in Wirklichkeit dasconst std::function<int(int)>
Teil und jetztf
können davon ausgehen, dassg
istconst
keine?In C++ ist nichts durchgesetzt, nur vorgeschlagen. Wie üblich, wenn Sie etwas dummes zu tun (dokumentierten Anforderungen der referentiellen Transparenz und übergeben Sie dann auch nicht-referentiell transparent-Funktion), erhalten Sie, was zu Ihnen kommt.
Diese Antwort öffnete mir die Augen. Bisher dachte ich, dass in diesem Fall die lambda nur mutiert, die eine Kopie für den aktuellen "run".
Ihr Kommentar öffnete meine Augen! 😀 ich hatte nicht den wahren Sinn dieser Antwort erst lese ich Ihren Kommentar.
Ich bin nicht einverstanden mit der grundlegenden Prämisse dieser Antwort. C++ hat kein Konzept von "Funktionen sollten immer den gleichen Wert zurückgeben" irgendwo sonst in der Sprache. Als design-Prinzip, würde ich Zustimmen, dass es ein guter Weg, um eine Funktion schreiben, aber ich glaube nicht, dass es hält Wasser wie das Grund für das standard-Verhalten.
InformationsquelleAutor Puppy
Dein code ist fast äquivalent zu dieser:
So könnte man denken, dass Lambda-Ausdrücke erzeugen Sie eine Klasse mit operator (), der standardmäßig const, es sei denn, Sie sagen, es ist veränderlich.
Können Sie auch alle Variablen erfasst innen [] (explizit oder implizit) als Mitglieder dieser Klasse: Kopien der Objekte, die für [=] oder Verweise auf die Objekte, die für [&]. Sie werden initialisiert, wenn Sie erklären Ihren lambda, als ob es eine versteckte Konstruktor.
const
odermutable
lambda Aussehen würde, wenn Sie umgesetzt werden, da entsprechende Benutzer-definierte Typen, die Frage ist (wie im Titel ausgearbeitet und durch die OP in den Kommentaren) warumconst
ist die Standardeinstellung, damit diese nicht beantworten.InformationsquelleAutor Daniel Muñoz
Die Frage ist, ist es "fast"? Ein häufiger use-case zu sein scheint zurück zu senden oder zu übergeben lambdas:
Ich denke, dass
mutable
ist nicht ein Fall von "fast". Ich als "capture-von-Wert" wie "erlauben Sie mir zu verwenden, dessen Wert nach der aufgenommenen Person stirbt" und nicht als "zulassen, mich zu ändern, eine Kopie davon". Aber vielleicht kann argumentiert werden.const
? Welchen Zweck hat es zu erreichen?mutable
scheint hier fehl am Platz, wennconst
ist nicht den Standard in der "fast" (:P) alles andere von der Sprache.Ich Wünsche
const
war das Standard, zumindest würden die Leute gezwungen werden, sich zu überlegen, const-correctness :/der Blick in die lambda-Papiere, die es scheint mir, Sie machen es standardmäßig
const
so konnten Sie es nennen, ob oder nicht die lambda-Objekt sternb. Zum Beispiel könnten Sie übergeben es an eine Funktion, die einstd::function<void()> const&
. Zu erlauben, dass der lambda-ändern Sie Ihren aufgezeichneten Kopien, die in den ursprünglichen Papieren der Daten-Mitglieder von der Schließung waren definiertmutable
intern automatisch. Jetzt müssen Sie manuell setzenmutable
im lambda-Ausdruck. Ich habe nicht gefunden eine ausführliche Begründung obwohl.Siehe open-std.org/JTC1/SC22/WG21/docs/papers/2008/n2651.pdf für einige details.
An diesem Punkt, für mich, die "echte" Antwort/Begründung scheint zu sein, "Sie nicht Arbeit um eine Implementierung detail" :/
InformationsquelleAutor Johannes Schaub - litb
FWIW, Herb Sutter, einem bekannten Mitglied der C++ - Standardisierung-Komitees, liefert eine andere Antwort auf diese Frage in Lambda Korrektheit und Usability-Probleme:
Seinem Papier über, warum dies sollte geändert werden in C++14. Es ist kurz, gut geschrieben, lesenswert, wenn man wissen will "was auf [Ausschussmitglied] Geist" mit Bezug auf diese Besonderheit.
InformationsquelleAutor akim
Sehen dieser Entwurf, unter 5.1.2 [expr.prim.lambda], Ziffer 5:
Bearbeiten auf litb Kommentar:
Vielleicht dachten Sie, der capture-Wert, so dass außerhalb der änderungen an den Variablen nicht reflektiert innerhalb der lambda? Verweise in beide Richtungen funktionieren, also das ist meine Erklärung. Weiß nicht, ob es gut ist wenn.
Bearbeiten auf kizzx2 Kommentar:
Die meisten Zeiten, wenn ein lambda-Ausdruck verwendet werden, ist als Funktor für-algorithmen. Die Standard -
const
ness können Sie verwendet werden, in einem Konstanten Umfeld, genauso wie die normalenconst
qualifizierte Funktionen verwendet werden können, dort aber nichtconst
qualifizierten diejenigen, die das nicht können. Vielleicht haben Sie einfach gedacht, zu machen, mehr intuitiv für jene Fälle, die wissen, was geht auf in Ihrem Geist. 🙂Meine Erklärung ist die, direkt unter das Zitat. 🙂 Es bezieht sich ein bisschen auf, was litb, sagt über die Lebensdauer der erfassten Gegenstände, sondern auch etwas weiter geht.
Oh ja, ich verpasst,: P Es ist auch eine andere gute Erklärung für eine gute Verwendung der capture-by-value. Aber warum sollte es
const
standardmäßig? Ich habe bereits eine neue Kopie, es scheint seltsam, nicht zu lassen, mich zu ändern es-vor allem, es ist nicht etwas grundsätzlich falsch mit ihm -- Sie wollen einfach nur, mich zu fügen Siemutable
.Siehe mein edit, vielleicht, dass macht keinen Sinn. 😐
Wenn wir könnten wieder von vorn anfangen, hätten wir wahrscheinlich
var
als ein Schlüsselwort zu erlauben, Veränderung und Konstanten als Standardwerte für alles andere. Jetzt wissen wir nicht, also müssen wir damit Leben. IMO, C++2011 kam ziemlich gut, wenn man bedenkt alles.InformationsquelleAutor Xeo
Müssen Sie denken, was ist der Verschluss Typ Ihrer Lambda-Funktion. Jedes mal, wenn Sie deklarieren ein Lambda-Ausdruck, der compiler erstellt eine Schließung geben, die nichts weniger als eine Unbenannte Klasse Erklärung mit Parametern (Umgebung, wo die Lambda-Ausdruck, wo erklärt) und der Funktion Anruf
::operator()
umgesetzt. Wenn Sie erfassen einer Variablen, die mit copy-by-value, erstellt der compiler einen neuenconst
Attribut in den Verschluss geben, so können Sie es nicht ändern innerhalb der Lambda-Ausdruck, weil es eine "nur Lesen"-Attribut, das ist der Grund, warum Sie nennen es ein "Schließung", weil Sie in irgendeiner Weise, die Sie schließen Ihren Lambda-Ausdruck kopieren Sie die Variablen aus den oberen Bereich in die Lambda Umfang. Wenn Sie das Schlüsselwort verwendenmutable
die erfasste Person wurde einnon-const
Attribut des closure-Typs. Dies ist, was bewirkt, dass die änderungen in das mutable-Variablen erfasst, die von Wert, nicht weitergegeben oberen Rahmen, aber halten Sie innerhalb der stateful Lambda.Immer versuchen Sie sich vorzustellen, die daraus resultierende Schließung Typ des Lambda-Ausdrucks, das hat mir sehr geholfen, und ich hoffe, es kann dir auch helfen.
InformationsquelleAutor Tarantula
n
ist nicht eine vorübergehende. n ist Mitglied der lambda-Funktion-Objekt, das Sie erstellen mit den lambda-Ausdruck. Die standardmäßige Erwartung ist, dass das aufrufen Ihres lambda ändert nicht seinen Zustand, daher ist es von const, um zu verhindern, dass Sie versehentlich geändertn
.IIRC, ich bezog mich auf das Problem, dass wenn jemand sagt, "temporär" verstehe ich, das es bedeutet Unbenannt temporäre Objekt, das die lambda selbst ist, aber es ist den Mitgliedern nicht. Und auch das von der "Innenseite" der lambda, ist es eigentlich egal, ob die lambda selbst ist temporär. Re-Lektüre die Frage, obwohl es scheint, dass der OP wollte nur sagen das "n innerhalb des lambda", wenn er sagte, "temporary".
InformationsquelleAutor Martin Ba
Gibt es jetzt einen Vorschlag zu lindern die Notwendigkeit
mutable
im lambda-Deklarationen: n3424Ja, es scheint wie ein verändern um des Veränderns Willen.
Obwohl um fair zu sein, ich erwarten, dass es wohl viele C++ - Entwickler, die nicht wissen, dass
mutable
ist auch ein Schlüsselwort in C++.InformationsquelleAutor usta
Müssen Sie verstehen, was Gefangennahme bedeutet! es ist die Erfassung nicht-argument übergeben! betrachten wir nun einige code-Beispiele:
Wie Sie sehen können, obwohl
x
wurde geändert, um20
die lambda ist immer noch die Rückkehr 10 (x
noch5
innerhalb der lambda)Ändern
x
innerhalb der lambda bedeutet die änderung der lambda sich bei jedem Aufruf (lambda mutiert bei jedem Aufruf). Zur Durchsetzung Richtigkeit der standard eingeführt, dermutable
Schlüsselwort. Durch die Angabe eines lambda-so wandelbar ist, sagen Sie, dass jeder Aufruf der lambda könnte zu einer Veränderung in den lambda-Ausdruck selbst. Lassen Sie sehen, ein anderes Beispiel:Das obige Beispiel zeigt, dass durch die Herstellung der lambda-veränderliche, wechselnde
x
im inneren des lambda "mutiert" die lambda bei jedem Aufruf ein neuer Wert vonx
hat nichts zu tun mit dem tatsächlichen Wert derx
in der main-FunktionInformationsquelleAutor Soulimane Mammar
Verlängern Hund die Antwort, lambda-Funktionen verwendet werden sollen,Reine Funktionen. Das bedeutet, dass jeder Aufruf einen eindeutigen input-set gibt immer die gleiche Ausgabe. Wir definieren Eingang als die Menge aller Argumente sowie alle erfassten Variablen, wenn der lambda-Ausdruck genannt.
In reinen Funktionen, Ausgang hängt ab von Eingabe und nicht auf einem internen Zustand. Daher kann der lambda-Funktion, wenn rein, nicht brauchen, um Ihren Zustand ändern und ist daher unveränderlich.
Wenn ein lambda-Ausdruck erfasst, die durch Verweis, schriftlich auf captured Variablen ist eine Belastung, die auf das Konzept der reinen Funktion, da alle eine Reine Funktion tun sollten, ist die Rückkehr eine Ausgabe, wenn die lambda nicht sicher mutieren, weil das schreiben geschieht auf externe Variablen. Auch in diesem Fall eine korrekte Verwendung impliziert, dass, wenn der lambda-Ausdruck aufgerufen, mit dem gleichen Eingang wieder, der output wird der gleiche sein jedes mal, trotz dieser Nebenwirkungen auf, die durch-ref-Variablen. Solche Nebenwirkungen sind nur Möglichkeiten, um wieder einige weitere Eingabe (z.B. ein update-Zähler) und könnte umformuliert werden in eine Reine Funktion, zum Beispiel bei der Rückkehr ein Tupel anstatt einen einzelnen Wert.
InformationsquelleAutor Attersson