【问题标题】:Best way to pass function as parameter将函数作为参数传递的最佳方法
【发布时间】:2016-04-07 00:35:21
【问题描述】:

在 C++ 中,有几种方法可以将函数作为参数传递,但我想了解每种方法的优势和优势,例如,从算法中查看函数的签名:

template <class RandomAccessIterator, class Compare>
  void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp);

为什么std算法使用模板传递函数而不是std::function?

为什么线程使用移动语义而算法函数不使用?

template <class Fn, class... Args>
explicit thread (Fn&& fn, Args&&... args);

PS:我忽略了 C 中用作函数指针的方式。

【问题讨论】:

  • 仅供参考,std::function post-dates std::sort(实际上是 C++11 之前标准库算法中的所有“可调用对象”)。跨度>

标签: c++ c++11


【解决方案1】:

为什么std算法使用模板传递函数而不是std::function?

C++98 中没有std::function。一种替代方法是拥有一个抽象的Comparator 基类,该基类具有一个虚拟成员函数,可以被具体的比较器类覆盖,但是模板版本更有效,因为它避免了虚拟调度的开销;如果Compare 是一个类类型,那么operator() 通常可以被内联。这也是反对今天使用std::function 的理由。

为什么线程使用移动语义而算法函数不使用?

C++98 中也没有右值引用。

很容易看出,现在我们有了右值引用和移动语义,不允许将值移动到线程中是愚蠢的(因为某些类型不可复制或不可有效复制)。

为什么std::sort 应该按值获取它的比较器?请参阅why function objects should be pass-by-value 进行讨论。

【讨论】:

  • 那么今天,将函数作为参数传递的最佳方式是泛型函数的线程方式,而 std::function 则传递给其他函数?
  • @Alex 什么是“泛型函数”?
  • 像 std::thread 这样的函数接收,具有任意数量和类型的参数
  • @Alex:如果函数的类型只能在运行时确定,或者如果它可以在运行时改变,你只需要使用std::function。如果可以在编译时确定,则没有理由使用std::function
【解决方案2】:

为什么std算法使用模板传递函数而不是std::function?

不需要std::function 作为排序,例如,直接在内部调用您的comp 可调用对象(无论是函数、函数调用运算符等),并在它退出时完成它。当您创建 std::function 的实例时,您正在存储可调用对象(可选地与一些参数绑定)。

另一方面,std::thread 在退出构造函数时需要存储FnArgs,因为它们被新生成的线程使用。

为什么线程使用移动语义而算法函数不使用?

同样,std::thread 存储您传递给构造函数的数据以及移动语义。另一方面,算法只是调用你的可调用对象,不需要存储它。

更新:

所以,如果你有一个内联函数,你可以遵循sort 语义并将函数作为模板参数传递。

否则,请使用std::function。这基本上就是std::thread 所做的——它将fnargs 绑定并将其存储为共享ptr。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-06-09
    • 1970-01-01
    • 2013-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-26
    相关资源
    最近更新 更多