如果需要性能,则在存储时按值传递。
假设您有一个名为“在UI线程中运行此函数”的函数。
std::future<void> run_in_ui_thread( std::function<void()> )
它在“ ui”线程中运行一些代码,然后future在完成时发出信号。(在UI线程应该用来弄乱UI元素的UI框架中很有用)
我们正在考虑两个签名:
std::future<void> run_in_ui_thread( std::function<void()> ) // (A)
std::future<void> run_in_ui_thread( std::function<void()> const& ) // (B)
现在,我们可能会如下使用它们:
run_in_ui_thread( [=]{
// code goes here
} ).wait();
这将创建一个匿名闭包(lambda),从中构造出一个闭包std::function,将其传递给run_in_ui_thread函数,然后等待其完成在主线程中的运行。
在情况(A)中,std::function会直接从我们的lambda构造,然后在中使用run_in_ui_thread。λ move进入std::function,因此任何可移动状态都有效地携带到其中。
在第二种情况下,将std::function创建一个临时变量,即lambda为move放入其中,然后将该临时文件std::function用于内的引用run_in_ui_thread。
到目前为止,还算不错-他们两个的表现相同。除了run_in_ui_thread要复制其函数参数以发送到ui线程执行之外!(它将在完成之前返回,因此它不能仅使用对其的引用)。对于情况(A),我们简单move的std::function其长期存储即可。在情况(B)中,我们被迫复制std::function。
那家商店使价值传递更加优化。如果有可能,您将存储的副本std::function,并按值传递。否则,这两种方法都大致等效:按值的唯一缺点是,如果您使用的是相同的笨重对象,std::function并且又有一个子方法使用另一个子方法,则该方法不可行。除非,move否则a的效率将与a相同const&。
现在,如果我们在 std::function。
假设std::function存储一些对象operator() const,但是它也具有一些mutable可以修改的数据成员(多么粗鲁!)。
在这种std::function<> const&情况下mutable修改后数据成员将传播到函数调用之外。在这种std::function<>情况下,他们不会。
这是一个相对奇怪的极端情况。
您想要std::function像对待其他任何重量轻,价格便宜的移动设备一样对待。移动很便宜,复制可能很昂贵。
sizeof(std::function)不会超过2 * sizeof(size_t),这是您考虑使用const引用的最小大小。