Чи законно нового виділення покажчика на функціонування?


33

Покажчики функцій не є простими покажчиками даних, оскільки вони не можуть бути збережені у покажчику недійсності *. Тим не менш, здається, що я можу зберігати копію вказівника функції в динамічній пам'яті (в gcc і clang), як у наведеному нижче коді. Чи законний такий код відповідно до стандарту C ++, чи, можливо, це якесь розширення компілятора?

Крім того, отриманий вказівник на функціональний покажчик поводиться як звичайний покажчик даних: я можу зберігати його в недійсності * та витягувати його з недійсності * 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 ;

}

2
Будь ласка, не використовуйте сирі покажчики функціоналу. Використовуйте std::functionзамість цього.
Якийсь програміст чувак

Вам не потрібен newакторський склад void*. void* ptr = &fcnPtr;працює так само добре, оскільки fcnPtrце об'єкт, а не функція.
волоський горіх

5
@Someprogrammerdude std::functionє стираним контейнером для зберігання довільного дзвінка, насправді не заміною функціональних покажчиків…
Michael Kenzel

7
(@Someprogrammerdude) Будь ласка, не використовуйте / рекомендуйте сліпо std::function. Це чудово для його здатності зберігати "поліморфні" функції (тобто що-небудь з правильним підписом, навіть якщо він містить стан, як у випадку з деякими лямбдами), але це також додає накладні витрати, які можуть не знадобитися. Вказівник на функцію - POD. А std::function- ні.
Метью

2
@Matthew Щоб бути справедливим, Адріан задається питанням про динамічне виділення вказівника на функцію та вказівку на нього стиранням типу void*, тому в контексті цього питання, std::functionздається, саме те, що вони шукали. Я згоден з тим, що загальне звільнення від функціональних покажчиків SPD є непристойним.
eerorika

Відповіді:


27

Хоча покажчики функцій не є об'єктними вказівниками, "покажчик на функцію якогось типу" все ще є типом об'єкта [basic.types] / 8 . Таким чином, покажчики функцій самі по собі є об'єктами, просто те, на що вони вказують, не є.

Таким чином, ви впевнені, що можете створити об’єкт типу вказівника функції за допомогою нового виразу ...


9

оскільки вони (функціональні покажчики) не можуть бути збережені у покажчику void *.

Насправді зберігання функціонального вказівника як a void*умовно підтримується. Це означає, що він може бути або не може зберігатися залежно від мовної реалізації. Якщо мовна реалізація підтримує динамічне завантаження, то, void*можливо, підтримується перетворення покажчика функції в . GCC, Clang та MSVC все це підтримують:

reinterpret_cast<void*>(&function);

Чи законно нового виділення покажчика на функціонування?

Звичайно. Усі вказівники, включаючи функціональні покажчики, є об'єктами, і всі об'єкти можуть бути розподілені динамічно.

Крім того, отриманий вказівник на покажчик функції поводиться як звичайний покажчик даних

Покажчик функції - це об’єкт. Вказівник на покажчик функції не тільки "поводиться як", але є вказівником на об'єкт.

Я можу зберігати його в void * та витягувати його з void * static_cast. Чи така поведінка гарантується Стандартом?

Перетворення між покажчиком на недійсним і покажчиком на об’єкт дозволено, так. І зворотне перетворення гарантовано дає вихідний покажчик.


Дякую. Але потім для перетворення покажчика функції в недійсний * (або навпаки) мені потрібно використовувати reinterpret_cast, правда?
Адріан

1
@ Адріан Так. Я додав приклад.
eerorika

Якщо хтось хоче виняток, можливо: dos модель середньої пам'яті + накладки. Функціональні покажчики більше, ніж покажчики даних у середній моделі, і накладки можуть бути використані для досягнення плагінів, якщо ви досить стараєтесь.
Джошуа
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.