Les pointeurs vers des fonctions ne sont pas de simples pointeurs de données car ils ne peuvent pas être stockés dans un pointeur void *. Néanmoins, il semble que je puisse stocker la copie d'un pointeur de fonction dans la mémoire dynamique (en gcc et clang) comme dans le code ci-dessous. Un tel code est-il légal selon la norme C ++, ou peut-être s'agit-il d'une sorte d'extension de compilateur?
De plus, le pointeur résultant vers le pointeur de fonction se comporte comme un pointeur de données simple: je peux le stocker dans void * et le récupérer de void * par static_cast. Ce comportement est-il garanti par la norme?
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
plutôt.new
lancervoid*
.void* ptr = &fcnPtr;
fonctionne aussi bien, carfcnPtr
est un objet, pas une fonction.std::function
est un conteneur de type effacé pour stocker un appel arbitraire, pas vraiment un remplacement pour les pointeurs de fonction…std::function
. C'est génial pour sa capacité à stocker des fonctions "polymorphes" (c'est-à-dire tout ce qui a la bonne signature, même s'il contient un état comme dans le cas de certains lambdas), mais cela ajoute également des frais généraux qui peuvent ne pas être nécessaires. Un pointeur vers une fonction est POD. Astd::function
ne l'est pas.void*
, donc dans le contexte de cette questionstd::function
semble être exactement ce qu'ils cherchaient. Je suis d'accord que le rejet général par SPD des pointeurs de fonction n'est pas valable.Réponses:
Bien que les pointeurs de fonction ne soient pas des pointeurs d'objet, le "pointeur vers une fonction d'un certain type" est toujours un type d'objet [basic.types] / 8 . Ainsi, les pointeurs de fonction sont eux-mêmes des objets, tout ce qu'ils pointent ne l'est pas.
Ainsi, vous pouvez bien sûr créer un objet de type pointeur de fonction via une nouvelle expression…
la source
En fait, le stockage d'un pointeur de fonction en tant que
void*
est pris en charge sous condition. Cela signifie qu'il peut ou non être stocké en fonction de l'implémentation du langage. Si l'implémentation du langage prend en charge le chargement dynamique, la conversion du pointeur de fonctionvoid*
est probablement prise en charge. GCC, Clang et MSVC soutiennent tous ceci:Sûr. Tous les pointeurs, y compris les pointeurs de fonction, sont des objets et tous les objets peuvent être alloués dynamiquement.
Le pointeur de fonction est un objet. Le pointeur vers un pointeur de fonction non seulement "se comporte comme", mais est un pointeur vers un objet.
La conversion entre le pointeur en vide et le pointeur en objet est autorisée, oui. Et la conversion aller-retour est garantie pour donner le pointeur d'origine.
la source