【问题标题】:Should we check a function not empty before applied with std::bind?我们应该在使用 std::bind 之前检查一个不为空的函数吗?
【发布时间】:2020-04-13 11:58:08
【问题描述】:
std::function<void(bool)> f;
std::function<void()> binded_f = std::bind(f, true);
std::cout << (f != nullptr) << " " << (binded_f != nullptr) << "\n";
f(true);
binded_f();

上面的代码给出了输出0 1,并且binded_f()在MSVC中与Unhandled exception at 0x00007FFE7B63A388 in: Microsoft C++ exception: std::bad_function_call at memory location 0x00000096960FA660. occurred崩溃。

貌似调用空函数f没问题,而应用std::bind后会crash。我们应该做什么?我们需要在绑定之前检查一个函数吗?

【问题讨论】:

    标签: c++ c++11 lambda std-function stdbind


    【解决方案1】:

    似乎调用null函数在这里输入代码f很好,而在std::bind之后 应用,它会崩溃。我们该怎么办?

    不,两者都有

    f(true);
    binded_f();
    

    将通过异常,您会从第一个函数调用(即f(true);)本身看到异常。 来自 cppreference.com std::function::operator()

    例外情况

    std::bad_function_call 如果*this 不存储可调用对象 函数目标,即!*this == true

    意思是f的调用显然是个例外。

    也适用于std::bind

    例外情况

    仅抛出 如果构造 std::decay&lt;F&gt;::type 来自 std::forward&lt;F&gt;(f) throws,或任何构造函数 std::decay&lt;Arg_i&gt;::type 来自对应 std::forward&lt;Arg_i&gt;(arg_i) throws 其中Arg_i 是第 i 个类型并且 arg_iArgs... args 中的第 i 个参数。

    由于f throws/构造失败,绑定的对象也会在调用时出现异常。


    我们需要在绑定之前检查一个函数吗?

    是的,出于上述原因。

    【讨论】:

      【解决方案2】:

      std::bad_function_call 已经发生在 f(true)

      在调用f 和调用std::bind 之前,您需要检查f 是否在这两种情况下都拥有一个函数。

      std::bind 需要一个 Callable 对象,而 std::function&lt;void(bool)&gt; f 本身是一个可调用对象。但是调用f 仅在它持有一个目标时才有效,因为它会在调用f 时将使用std::forward 的调用转发到存储的目标。

      std::function&lt;void()&gt; binded_f 拥有一个目标,该目标将调用f 的存储副本,并以true 作为第一个参数,因此binded_f 本身拥有一个有效目标,但该目标在尝试调用f 时使用true 将失败结果为std::bad_function_call,因为f 没有有效的目标。

      如果您将绑定替换为 lambda,这会变得更加明显。

      std::function<void(bool)> f;
      std::function<void()> binded_f = [f]() {
         return f(true);
      };
      
      std::cout << (f != nullptr) << " " << (binded_f != nullptr) << "\n";
      f(true);
      binded_f();
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-09-16
        • 1970-01-01
        • 1970-01-01
        • 2020-04-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多