如果需要性能,则在存储时按值传递。
假设您有一个名为“在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引用的最小大小。