功能开销
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
采取 allocator
的 function
构造函数不再是类型的一部分。因此,无法管理分配。
调用 function
也比直接调用内容慢。由于任何 function
实例都可以保持任何可调用,因此通过 function
的调用必须是间接的。调用 function
的开销是虚函数调用的顺序。