c – 在这种情况下是否可以避免复制lambda仿函数?

我在C 11中使用lambda制作了一个终极模拟器,如下所示:

#include <cstdio>

template<typename Functor>
struct Finalizer
{
    Finalizer(Functor& func) : func_(func) {} // (1)
    ~Finalizer() { func_(); }

private:
    Functor func_; // (2)
};

template<typename functor>
Finalizer<functor> finally(functor& func)
{
    return Finalizer<functor>(func); (3)
}

int main()
{
    int a = 20;

    // print the value of a at the escape of the scope
    auto finalizer = finally([&]{ printf("%d\n", a); }); // (4)
}

代码按预期工作,但在Finalizer struct(1)的ctor处有不需要的copy ctor调用(lambda functor). (值得庆幸的是,RVO可以避免在finally函数(3 – > 4)的return语句中进行复制构造.)

编译器不会消除copy ctor调用(至少在vc10中 – gcc可能会对其进行优化),如果Finalizer struct(2)中的仿函数类型被更改为引用它,则会因为finally调用时的lambda参数而崩溃( 4)是r值.

当然,代码可以像下面那样“优化”

template<typename Functor>
struct Finalizer
{
    Finalizer(Functor& func) : func_(func) {}
    ~Finalizer() { func_(); }

private:
    Functor& func_;
};

int main()
{
    int a = 20;

    auto finalizer = [&]{ printf("%d\n", a); };
    Finalizer<decltype(finalizer)> fin(finalizer);
}

没有开销,只有一个printf调用放在范围的末尾.但是……我不喜欢它. :(我试图用宏包装它,但它需要声明两个“名称” – 一个用于lambda对象,另一个用于终结器对象.

我的目标很简单 –

>应该消除可以避免的每个不必要的性能开销.理想情况下,应该没有函数调用,每个过程都应该内联.
>保持简洁的表达作为效用函数的目的.允许使用宏,但不鼓励.

有没有解决办法避免这种情况?

最佳答案
我认为lambdas有移动构造函数?如果是这样,如果你最终只使用rvalues,那么&&而前进将移动而不是复制.

#include <cstdio>

template<typename Functor>
struct Finalizer
{
    Finalizer(Functor&& func) : func_(std::forward(func)) {} // (1)
    ~Finalizer() { func_(); }

private:
    Functor func_; // (2)
};

template<typename functor>
Finalizer<std::remove_reference<functor>::type> finally(functor&& func)
{
    return Finalizer<std::remove_reference<functor>::type>(std::forward(func)); // (3)
}

int main()
{
    int a = 20;

    // print the value of a at the escape of the scope
    auto finalizer = finally([&]{ printf("%d\n", a); }); // (4)
}

应该可以找到更加智能的东西,它也可以正确地使用左值,这样你就可以编译’优化’版本,并且当它无法移动时会复制.在这种情况下,我建议您使用像Functor< std :: remove_reference< functor> :: type>这样的东西.确保Functor的类型正确,无论参数是否通过&或者&&管他呢.

转载注明原文:c – 在这种情况下是否可以避免复制lambda仿函数? - 代码日志