新分配指向功能的指针合法吗?


33

函数指针不是纯数据指针,因为它们不能存储在void *指针中。尽管如此,似乎我可以像下面的代码一样将功能指针的副本存储在动态内存中(在gcc和clang中)。根据C ++标准,这样的代码合法吗,或者这是某种编译器扩展?

而且,指向功能指针的结果指针的行为就像普通的数据指针:我可以将其存储在void *中,并通过static_cast从void *中检索它。该行为是否受到标准的保证?

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。它具有存储“多态”函数的能力(即,具有正确签名的任何东西,即使它包含某些lambda的状态,也是如此),但它也增加了不必要的开销。指向函数的指针是POD。A std::function不是。
马修

2
@Matthew公平地说,Adrian询问动态分配给函数的指针并使用类型擦除来指向它void*,因此在这个问题的上下文中,这std::function似乎正是他们想要的。我确实同意SPD对函数指针的一般解雇是不合理的。
eerorika

Answers:


27

尽管函数指针不是对象指针,但是“某种类型的函数的指针”仍然是对象类型[basic.types] / 8。因此,函数指针本身就是对象,而它们指向的对象却不是。

因此,您肯定可以通过新表达式创建函数指针类型的对象。


9

因为它们(函数指针)不能存储在void *指针中。

实际上,void*有条件地支持将函数指针存储为a 。这意味着它可以存储也可以不存储,具体取决于语言实现。如果语言实现支持动态加载,则void*可能支持转换函数指针。GCC,Clang和MSVC都支持此功能:

reinterpret_cast<void*>(&function);

新分配指向功能的指针合法吗?

当然。所有指针(包括函数指针)都是对象,并且可以动态分配所有对象。

此外,结果指向功能指针的指针的行为就像普通数据指针一样

函数指针是一个对象。指向函数指针的指针不仅“表现为”,而且指向对象的指针。

我可以将其存储在void *中,并通过static_cast从void *中检索它。该行为是否受到标准的保证?

是的,允许在指向void的指针和指向对象的指针之间进行转换。并且往返转换可以保证产生原始指针。


谢谢。但是然后要将函数指针转换为void *(或反之),我需要使用reinterpret_cast,对吗?
阿德里安

1
@Adrian是的。我加了一个例子。
eerorika

如果有人想例外:dos中型内存模型+覆盖。在中等模型中,函数指针比数据指针大,如果您足够努力,则可以使用覆盖来实现插件。
约书亚
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.