Objekte haben Lebensdauern; Funktionen nicht. Funktionen leben nicht oder sterben nicht; sie existieren immer. Als solche kann eine Funktion nicht "außerhalb des Gültigkeitsbereichs" gehen, noch kann die Funktion, auf die durch einen zuvor gültigen Funktionszeiger gezeigt wird, verschwinden. Unabhängig davon, woher sie kommen, sind Funktionszeiger immer gültig.
Nun ignoriert dies dynamisches Laden und so weiter, aber das ist extra-Standard-Verhalten.
Der Funktionszeiger, den Sie von einem Lambda erhalten, ist ein Funktionszeiger. Es ist nicht besonders oder magisch. Es verhält sich daher nicht anders als jeder andere Funktionszeiger.
Ist es möglich, dass das Ergebnis der Umstellung auf void (*)() zeigt auf etwas, das eine Memberfunktion aufruft, auf ein Objekt gebunden?
Das ist eine viel komplexere Frage.Eine, über die der Standard eher unterspezifiziert scheint. Der Standard sagt nur:
die Adresse einer Funktion, die, wenn sie aufgerufen wird, den gleichen Effekt hat wie das Aufrufen des Funktionsaufrufoperators des Schließungstyps.
Was "der gleiche Effekt" genau bedeutet, ist die Frage. Man könnte argumentieren, dass "derselbe Effekt" bedeutet, zu tun, was der Funktionsaufrufoperator getan hätte, indem er die gleiche Folge von Anweisungen ausführt. Man könnte auch argumentieren, dass "derselbe Effekt" bedeuten würde, das Schließobjekt selbst aufzurufen.
Der letztere Fall klingt vielleicht schwierig zu implementieren, aber denken Sie daran, dass Compiler Magie verwendet werden kann. Die Schließung könnte einen instanzspezifischen Funktionszeiger zurückgeben, der auf Anfrage durch die Schließung zugewiesen wird. Oder etwas Ähnliches.
Der nicht normative Text scheint in dieser Angelegenheit nicht sehr aufschlussreich zu sein. Es ist ein Beispiel für einen Verschluss für ein (generisch) Lambda, das sagt dieser:
template<class T> auto operator()(T t) const { ... }
template<class T> static auto lambda_call_operator_invoker(T a) {
// forwards execution to operator()(a) and therefore has
// the same return type deduced
...
}
Der Kommentar in Frage schlägt vor Weiterleitung, aber das würde erfordern, dass der statische Aufruf eine neue Instanz des Konstrukt Lambda für die Weiterleitung mit.
Insgesamt macht der Standard es nicht klar, ob der Aufruf des generierten Funktionszeigers nach der Zerstörung der Schließung zulässig ist.
Interessante Frage. Da der Zeiger auf ein * static * "invoker" -Mitglied zeigt, hat das statische Mitglied keine andere Wahl, als ein Dummy-Objekt zu verwenden, um 'operator()' des Lambda aufzurufen (weil das letztere nicht-statisch ist). Dieser Dummy sollte entweder lokal für den "Invoker" oder statisch sein, d. H. Er sollte in dem obigen Kontext gut funktionieren. Aber ich sehe diese Garantie nicht sofort in der Sprachspezifikation. Die Sprachspezifikation postuliert nicht einmal die Existenz dieses Dummy-Objekts. – AnT
@ant Warum? Es muss den gleichen Code ausführen. Warum muss es in 'operator()' sein? 'operator()' könnte durch Aufruf der statischen Funktion implementiert werden, die 'operator void (*)()()' gibt – Yakk
zurück Ich wünschte, alle langatmigen Fragen wären so kurz –