Die Lambda-Ausdruck [&foo](int i){f(i, foo);}
Compiler führt eine Verschluss Klasse, so etwas zu erzeugen (aber nicht ganz korrekt):
class _lambda
{
Foo& mFoo; // foo is captured by reference
public:
_lambda(Foo& foo) : mFoo(foo) {}
void operator()(int i) const
{
f(i, mFoo);
}
};
Daher Die Deklaration Foo foo([&foo](int i){f(i, foo);});
wird als Foo foo(_lambda(foo));
behandelt. Das Erfassen von foo
selbst beim Konstruieren hat in dieser Situation kein Problem, da hier nur seine Adresse benötigt wird (Referenzen werden normalerweise über Zeiger implementiert).
Der Typ std::function<void(int)>
intern kopieren diese Lambda-Typ konstruieren, was bedeutet, dass die Foo Konstruktorargument fn
eine Kopie _lambda
Objekt enthält (das hält eine Referenz (d.h. mFoo) auf Ihrer foo
).
Dies bedeutet, dass baumelnden Referenz Problem in einigen Situationen auftreten kann, zum Beispiel:
std::vector<std::function<void(int)>> vfn; // assume vfn live longer than foo
class Foo {
Foo(std::function<void(int)> fn) { vfn.push_back(fn); }
}
void f(int i, Foo& foo) { /* stuff with i and foo */ }
Foo foo([&foo](int i){f(i, foo);});
....
void ff()
{
// assume foo is destroyed already,
vfn.pop_back()(0); // then this passes a dangling reference to f.
}
Wahrscheinlich erwähnenswert, dass, wenn Sie das Lambda im Konstruktor verwenden, könnten schlimme Dinge passieren. –
Wenn Sie es durch Kopieren erfassen, erhalten Sie eine Warnung mit clang 'Variable ist nicht initialisiert, wenn innerhalb ihrer eigenen Initialisierung verwendet ' – Drax