Ich habe versucht, eine Lambda-Funktion einen Wert durch Referenz ohne eine Kopie des referenzierten Wertes zu machen. Mein Codebeispiel veranschaulicht das Problem. Es kompiliert und läuft ok, aber mit der "//" kommentierten Zeile anstelle der Zeile oben, tut es nicht. Ich habe zwei Lösungen gefunden (beide in meinem Beispiel dargestellt):Lambda Fct Rückkehr Referenz
- wickeln Sie das Ergebnis mit std :: ref()
- einen Zeiger anstelle eines Verweises
Aber beide Abhilfen sind nicht, was ich wirklich will, und ich verstehe nicht, warum sie notwendig sind: Der Ausdruck "makeRefA()" hat bereits den Typ, den die Lambda-Funktion zurückgibt (const A &) und muss daher weder kopiert noch konvertiert werden. Übrigens: Der Kopierkonstruktor wird wirklich genannt, wenn ich ihn nicht explizit lösche (was in meinem "echten" Code ein Performance-Problem ist). Für mich sieht es aus wie ein Compiler-Bug, aber ich habe mit mehreren C++ 11-Compiler versucht, die alle den gleichen Fehler zeigen. Gibt es also etwas Besonderes bezüglich der "Return" -Anweisung in einer Lambda-Funktion?
#include <functional>
#include <iostream>
struct A {
A(int i) : m(i) { }
A(const A&) = delete;
int m;
};
void foo(const A & a) {
std::cout << a.m <<'\n';
}
const A & makeRefA() {
static A a(3);
return a;
}
int main() {
std::function<const A&()> fctRef = [&]
{ return std::ref(makeRefA()); }; //compiles ok
//{ return makeRefA(); }; //error: use of deleted function 'A::A(const A&)'
foo(fctRef());
std::function<const A*()> fctPtr =
[&] { return &makeRefA(); };
foo(*fctPtr());
return 0;
}
Ausgang:
3
3
"Es wird eine Referenz zurückgeben, wenn der Ausdruckstyp eine Referenz ist" <- Korrekt-isch. Der Ausdruck * type * wird niemals eine Referenz sein, aber Sie erhalten die richtige Antwort, wenn Sie so darüber nachdenken. – Barry
Am besten Antwort, danke! – Stefan
Es funktioniert auch ohne die zusätzlichen Klammern, dh std :: function fctRef = [&]() -> declltype (makeRefA()) {return makeRefA();}; –
Stefan