Указатели на функции не являются обычными указателями данных, поскольку они не могут быть сохранены в указателе void *. Тем не менее, кажется, что я могу сохранить копию указателя функции в динамической памяти (в gcc и clang), как в коде ниже. Является ли такой код законным в соответствии со стандартом C ++, или, возможно, это своего рода расширение компилятора?
Более того, результирующий указатель на указатель на функцию ведет себя как простой указатель данных: я могу сохранить его в void * и извлечь его из void * с помощью static_cast. Это поведение гарантировано Стандартом?
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
вместо этого.new
бросать наvoid*
.void* ptr = &fcnPtr;
работает так же хорошо, такfcnPtr
как это объект, а не функция.std::function
- это стертый контейнер для хранения произвольного вызываемого объекта, который на самом деле не является заменой для указателей на функции…std::function
. Он отлично подходит для хранения «полиморфных» функций (т. Е. Всего, что имеет правильную сигнатуру, даже если он содержит состояние, как в случае некоторых лямбд), но это также добавляет накладные расходы, которые могут не понадобиться. Указатель на функцию - это POD. Аstd::function
это не так.void*
, поэтому в контексте этого вопроса,std::function
похоже, именно то, что они искали. Я согласен с тем, что общее отклонение указателей функций SPD несостоятельно.Ответы:
Хотя указатели на функции не являются указателями на объекты, «указатель на функцию некоторого типа» все еще является типом объекта [basic.types] / 8 . Таким образом, указатели функций сами по себе являются объектами, просто на что они указывают, это не так.
Таким образом, вы можете создать объект с указателем на функцию с помощью нового выражения…
источник
На самом деле, сохранение указателя функции как
void*
условно поддерживается. Это означает, что он может или не может быть сохранен в зависимости от языковой реализации. Если языковая реализация поддерживает динамическую загрузку, то,void*
вероятно, поддерживается преобразование указателя функции в . GCC, Clang и MSVC поддерживают это:Конечно. Все указатели, включая указатели функций, являются объектами, и все объекты могут быть размещены динамически.
Указатель на функцию является объектом. Указатель на указатель на функцию не только «ведет себя как», но и является указателем на объект.
Преобразование между указателем на void и указателем на объект разрешено, да. И преобразование туда-обратно гарантированно даст оригинальный указатель.
источник