如果您想要性能,请在存储时按值传递。
假设您有一个名为“在 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
. lambda 是move
d 到 中的std::function
,因此任何可移动状态都可以有效地带入其中。
在第二种情况下,std::function
创建了一个临时对象,将 lambdamove
放入其中,然后std::function
在run_in_ui_thread
.
到目前为止,一切都很好——他们两个的表现是一样的。除了将run_in_ui_thread
复制其函数参数以发送到 ui 线程执行!(它会在完成之前返回,所以它不能只使用对它的引用)。对于情况(A),我们简单move
的std::function
将其放入长期存储。在情况 (B) 中,我们被迫复制std::function
.
那家商店使价值传递更加优化。如果您有任何可能存储 的副本,请std::function
按值传递。否则,任何一种方式都大致等效:按值的唯一缺点是,如果您采用相同的体积std::function
并且有一个又一个子方法使用它。除此之外, amove
将与 a 一样有效const&
。
现在,如果我们在std::function
.
假设std::function
存储了一些带有 a 的对象operator() const
,但它也有一些mutable
它修改的数据成员(多么粗鲁!)。
在这种std::function<> const&
情况下,mutable
修改的数据成员将传播到函数调用之外。在这种std::function<>
情况下,他们不会。
这是一个比较奇怪的极端案例。
你想像对待std::function
任何其他可能很重、便宜的可移动字体一样对待。搬家很便宜,复制可能很贵。