功能开销

std::function 会导致很大的开销。因为 std::function 具有[value semantics] [1],所以它必须将给定的 callable 复制或移动到自身中。但由于它可以采用任意类型的 callable,因此它经常需要动态分配内存来执行此操作。

一些 function 实现具有所谓的小对象优化,其中小类型(如函数指针,成员指针或具有极少状态的函子)将直接存储在 function 对象中。但即便如此,只有在类型为 noexcept 移动构造时才有效。此外,C++标准并不要求所有实现都提供一个。

考虑以下:

//Header file
using MyPredicate = std::function<bool(const MyValue &, const MyValue &)>;

void SortMyContainer(MyContainer &C, const MyPredicate &pred);

//Source file
void SortMyContainer(MyContainer &C, const MyPredicate &pred)
{
    std::sort(C.begin(), C.end(), pred);
}

模板参数将是 SortMyContainer 的首选解决方案,但我们假设无论出于何种原因这都是不可能或不可取的。SortMyContainer 不需要将 pred 存储在自己的调用之外。然而,如果赋予它的仿函数具有一些非平凡的大小,pred 可能会很好地分配内存。

function 分配内存,因为它需要复制/移动的东西; function 获得它所给予的可调用权。但是 SortMyContainer 不需要拥有可调用的东西; 它只是引用它。所以在这里使用 function 是过度的; 它可能是有效的,但它可能不是。

没有标准库函数类型仅引用可调用函数。因此,必须找到替代解决方案,或者你可以选择承担开销。

此外,function 没有有效的方法来控制对象的内存分配来自何处。是的,有采取 allocator 构造函数,但[许多实现不正确地实现他们…甚至根本 ] [2]。

Version >= C++ 17

采取 allocatorfunction 构造函数不再是类型的一部分。因此,无法管理分配。

调用 function 也比直接调用内容慢。由于任何 function 实例都可以保持任何可调用,因此通过 function 的调用必须是间接的。调用 function 的开销是虚函数调用的顺序。