Los punteros a funciones no son punteros de datos simples ya que no pueden almacenarse en un puntero nulo *. No obstante, parece que puedo almacenar la copia de un puntero de función en la memoria dinámica (en gcc y clang) como en el código a continuación. ¿Es legal ese código de acuerdo con el estándar C ++, o tal vez esta es una especie de extensión del compilador?
Además, el puntero resultante a puntero de función se comporta como un puntero de datos simple: puedo almacenarlo en void * y recuperarlo de void * mediante static_cast. ¿Es este comportamiento garantizado por la Norma?
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
lugar.new
para lanzarvoid*
.void* ptr = &fcnPtr;
funciona igual de bien, ya quefcnPtr
es un objeto, no una función.std::function
es un contenedor de tipo borrado para almacenar una llamada arbitraria, no es realmente un reemplazo para los punteros de función ...std::function
. Es excelente por su capacidad para almacenar funciones "polimórficas" (es decir, cualquier cosa con la firma correcta, incluso si contiene el estado como en el caso de algunas lambdas), pero eso también agrega una sobrecarga que puede no ser necesaria. Un puntero a una función es POD. Astd::function
no lo es.void*
, por lo que en el contexto de esta preguntastd::function
parece ser exactamente lo que estaban buscando. Estoy de acuerdo en que el rechazo general de SPD de los punteros de función no es sólido.Respuestas:
Si bien los punteros de función no son punteros de objeto, el "puntero a función de algún tipo" sigue siendo un tipo de objeto [basic.types] / 8 . Por lo tanto, los punteros de función son en sí mismos objetos, lo que apuntan no lo es.
Por lo tanto, puede crear un objeto de tipo puntero de función mediante una nueva expresión ...
fuente
En realidad, el almacenamiento de un puntero de función como a
void*
se admite condicionalmente. Esto significa que puede o no puede almacenarse dependiendo de la implementación del lenguaje. Si la implementación del lenguaje admite la carga dinámica, entoncesvoid*
probablemente se admite la conversión del puntero de función . GCC, Clang y MSVC son compatibles con esto:Por supuesto. Todos los punteros, incluidos los punteros de función, son objetos y todos los objetos pueden asignarse dinámicamente.
El puntero de función es un objeto. El puntero a un puntero de función no solo "se comporta como", sino que es un puntero a un objeto.
Se permite la conversión entre puntero a vacío y puntero a objeto, sí. Y la conversión de ida y vuelta garantiza el puntero original.
fuente