Zeiger auf Funktionen sind keine einfachen Datenzeiger, da sie nicht in einem void * -Zeiger gespeichert werden können. Es scheint jedoch, dass ich die Kopie eines Funktionszeigers im dynamischen Speicher (in gcc und clang) wie im folgenden Code speichern kann. Ist ein solcher Code gemäß C ++ Standard legal oder handelt es sich um eine Art Compiler-Erweiterung?
Darüber hinaus verhält sich der resultierende Zeiger auf den Funktionszeiger wie ein einfacher Datenzeiger: Ich kann ihn in void * speichern und durch static_cast aus void * abrufen. Ist dieses Verhalten durch den Standard garantiert?
int main()
{
extern void fcn();
void (*fcnPtr)() = &fcn;
void (**ptrToFcnPtr)() = nullptr;
//Make the copy of fcnPtr on the heap:
ptrToFcnPtr = new decltype(fcnPtr)(fcnPtr);
//Call the pointed-to function :
(**ptrToFcnPtr)();
//Save the pointer in void* :
void *ptr = ptrToFcnPtr;
//retrieve the original ptr:
auto myPtr = static_cast< void(**)() > (ptr) ;
//free memory:
delete ptrToFcnPtr ;
}
std::function
stattdessen.new
zu besetzenvoid*
.void* ptr = &fcnPtr;
funktioniert genauso gut, dafcnPtr
es sich um ein Objekt handelt, nicht um eine Funktion.std::function
ist ein typenlöschender Container zum Speichern eines beliebigen aufrufbaren, nicht wirklich ein Ersatz für Funktionszeiger…std::function
. Es ist großartig für seine Fähigkeit, "polymorphe" Funktionen zu speichern (dh alles mit der richtigen Signatur, auch wenn es den Status wie bei einigen Lambdas enthält), aber das erhöht auch den Overhead, der möglicherweise nicht benötigt wird. Ein Zeiger auf eine Funktion ist POD. Astd::function
ist nicht.void*
Kontext dieser Fragestd::function
scheint es also genau das zu sein, wonach sie gesucht haben. Ich stimme zu, dass die generelle Ablehnung von Funktionszeigern durch die SPD nicht stichhaltig ist.Antworten:
Während Funktionszeiger keine Objektzeiger sind, ist "Zeiger auf eine Funktion eines Typs" immer noch ein Objekttyp [basic.types] / 8 . Funktionszeiger sind also selbst Objekte, genau das, worauf sie zeigen, ist es nicht.
So können Sie sicher ein Objekt vom Typ Funktionszeiger über einen neuen Ausdruck erstellen…
quelle
Das Speichern eines Funktionszeigers als
void*
wird tatsächlich bedingt unterstützt. Dies bedeutet, dass es je nach Sprachimplementierung entweder gespeichert werden kann oder nicht. Wenn die Sprachimplementierung das dynamische Laden unterstützt, wirdvoid*
wahrscheinlich das Konvertieren des Funktionszeigers in unterstützt. GCC, Clang und MSVC unterstützen dies alle:Sicher. Alle Zeiger, einschließlich Funktionszeiger, sind Objekte und alle Objekte können dynamisch zugewiesen werden.
Funktionszeiger ist ein Objekt. Der Zeiger auf einen Funktionszeiger "verhält sich nicht nur als", sondern ist ein Zeiger auf ein Objekt.
Die Konvertierung zwischen Zeiger auf void und Zeiger auf Objekt ist zulässig, ja. Die Roundtrip-Konvertierung liefert garantiert den ursprünglichen Zeiger.
quelle