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

时间:2017-03-07 14:37:58

标签: c++ c++11 std-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 ++标准草案中(我快速检查但到目前为止没有看到任何内容)。

2 个答案:

答案 0 :(得分:12)

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

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

当您调用operator()时,如果您使用参数调用目标,则需要返回会发生的情况。

std::function中作为副本存储的函数对象副本的“body”中,如果重新分配给std::function,则会破坏旧的目标函数对象。

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

但是,如果您已经存储了函数对象(lambdas,手动的,其他std::functionstd::bind等),那么在您执行的任务中当this被销毁时,进入类中运行方法的通常规则。简而言之,您将无法再依赖实例的“本地状态”执行任何操作。

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

你可以看到,这可能很脆弱。

答案 1 :(得分:-1)

如果你在没有经过适当考虑和代码文档的情况下这样做,它可能会回来咬你,但没有合理的理由说明它为什么不能工作。

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

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