【问题标题】:Is it legal to new-allocate a pointer to function?新分配指向函数的指针是否合法?
【发布时间】:2020-02-04 12:21:54
【问题描述】:

指向函数的指针不是纯数据指针,因为它们不能存储在 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 ;

}

【问题讨论】:

  • 请不要使用原始函数指针。请改用std::function
  • 您不需要将new 转换为void*void* ptr = &amp;fcnPtr; 也同样有效,因为 fcnPtr 是一个对象,而不是一个函数。
  • @Someprogrammerdude std::function 是一个类型擦除的容器,用于存储任意可调用对象,而不是真正的函数指针的替代品……
  • (@Someprogrammerdude) 请不要盲目使用/推荐std::function。它能够存储“多态”函数(即任何具有正确签名的东西,即使它包含某些 lambda 的状态)的能力非常好,但这也增加了可能不需要的开销。指向函数的指针是 POD。 std::function 不是。
  • @Matthew 公平地说,Adrian 正在询问动态分配指向函数的指针并使用类型擦除void* 指向它,所以在这个问题的上下文中std::function 似乎是正是他们想要的。我同意 SPD 对函数指针的普遍解雇是不合理的。

标签: c++


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

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

    实际上,有条件地支持将函数指针存储为void*。这意味着它可以或不能存储取决于语言实现。如果语言实现支持动态加载,那么转换void* 中的函数指针可能是支持的。 GCC、Clang 和 MSVC 都支持这个:

    reinterpret_cast<void*>(&function);
    

    新分配一个指向函数的指针合法吗?

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

    此外,指向函数指针的结果指针表现为普通数据指针

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

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

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

    【讨论】:

    • 谢谢。但是随后要将函数指针转换为 void*(或相反),我需要使用 reinterpret_cast,对吗?
    • @Adrian 是的。我添加了一个示例。
    • 如果有人想要一个例外可能:dos 中内存模型 + 覆盖。中型模型中函数指针比数据指针大,如果你足够努力,可以使用覆盖来实现插件。
    猜你喜欢
    • 1970-01-01
    • 2015-11-25
    • 2011-11-15
    • 2013-01-16
    • 1970-01-01
    • 1970-01-01
    • 2021-02-14
    • 1970-01-01
    • 2012-05-16
    相关资源
    最近更新 更多