Lambda到std::函数的转换性能

Lambda to std::function conversion performance

本文关键字:转换 性能 函数 std Lambda      更新时间:2023-10-16

我想使用lambda函数异步调用引用计数对象的方法:

void RunAsync(const std::function<void()>& f) { /* ... */ }
SmartPtr<T> objPtr = ...
RunAsync([objPtr] { objPtr->Method(); });

创建lambda表达式显然会创建一个副本,但我现在遇到的问题是,将lambda表达式转换为std::function对象也会创建我的智能指针的一堆副本,每个副本都会增加引用计数。

下面的代码应该演示这种行为:
#include <functional>
struct C {
    C() {}
    C(const C& c) { ++s_copies; }
    void CallMe() const {}
    static int s_copies;
};
int C::s_copies = 0;
void Apply(const std::function<void()>& fct) { fct(); }
int main() {
    C c;
    std::function<void()> f0 = [c] { c.CallMe(); };
    Apply(f0);
    // s_copies = 4
}

虽然之后引用的数量会恢复正常,但出于性能原因,我希望防止太多的引用操作。我不确定所有这些复制操作是从哪里来的。

是否有任何方法来实现这与我的智能指针对象的更少的副本?

更新:编译器是Visual Studio 2010.

std::function可能不会像自定义函子那样快,除非编译器对简单的情况实现了一些严肃的特殊处理。

但当move合适时,引用计数问题是复制的症状。正如其他人在评论中指出的那样,MSVC没有正确地实现move。您所描述的用法只需要移动,而不需要复制,因此永远不应该改变引用计数。

如果可以的话,试着用GCC编译,看看问题是否消失了。

转换为std::function 应该只使移动的lambda。如果没有这样做,那么可以说std::function的实现或规范中存在错误。此外,在上面的代码中,我只能看到原始c两个副本,一个用于创建lambda,另一个用于从中创建std::function