在被调用函数中更改函数指针 (std::function) 是否安全?

Is it safe to change a function pointer (std::function) inside a called function?

我有一个 std::function 指向一个函数。在这个函数中,我将指针更改为另一个函数。

std::function<void()> fun;

void foo() {
    std::cout << "foo\n";
}

void bar() {
    std::cout << "bar\n";
    fun = foo;
}

int main() {
    fun = bar;
    fun();
    fun();
}

我看不出有任何问题,而且工作正常(参见 here),但是我不确定这样做是否合法。我有什么想念的吗?也许在 c++ 标准草案中(我快速检查但到目前为止没有看到任何东西)。

如果你在没有适当考虑的情况下在代码文档中这样做,它可能会反咬你一口,但没有合乎逻辑的理由说明它不起作用。

在 c++ 中,不需要函数的地址,也不需要在 return 编码的函数内。

如果它在某种语言中不起作用,编译器可能不会接受它 - 如果它是一个半不错的编译器。

这对于函数指针是合法的。

当您使用目标分配或构建 std::function 时,它会创建目标的 copy。在将函数分配给 std::function 的情况下,这实际上将函数指针存储为目标对象。

当您调用 operator() 时,需要 return 如果您使用参数调用该目标会发生什么。

在 "body" 函数对象的副本中存储为 std::function 中的副本,如果您重新分配给 std::function,这将破坏旧的目标函数对象。

销毁函数指针不会影响在指向的函数内执行的代码的有效性。

但是,如果您存储了函数 objects(lambdas、手动的、其他 std::functions、std::bind 等),在当 this 被销毁时,您将 运行 分配到 运行 在 class 中调用一个方法的通常规则。简而言之,您将无法再做任何依赖于您实例的 "local state" 的事情。

std::function<void()> fun;
struct bob {
  std::string name;
  bob* next = 0;
  void operator()() const {
    std::cout << name << "\n";
    if (next) fun = *next;
    // undefined behavior:
    // std::cout << name << "\n";
  }
};
bob foo = {"foo"};
bob bar = {"bar", &foo};

int main() {
  fun = bar;
  fun();
  fun();
}

live example.

如您所见,这可能很脆弱。