如果您想要性能,请在存储时按值传递。
假设您有一个名为“在 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 是moved 到 中的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任何其他可能很重、便宜的可移动字体一样对待。搬家很便宜,复制可能很贵。