我应该通过const引用传递lambda吗? [英] Should I pass a lambda by const reference.

查看:120
本文介绍了我应该通过const引用传递lambda吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

通常,当接受lambda作为函数(按值传递的模板类)的参数时,使用以下模式:

Typically I use the following pattern when accepting a lambda as an argument to a function (A template class passed-by-value):

template <class Function>
void higherOrderFunction(Function f) {
     f();
}

此副本是否(关闭)自变量?
如果是这样,那么通过const引用接受lambda会有什么问题吗?

Does this copy (the closure of) the argument? If so, is there anything wrong with accepting the lambda by const reference instead?

template <class Function>
void higherOrderFunction(const Function& f) {
  f();
}

一个简单的测试似乎表明它可以正常工作,但我想知道

A simple test seems to indicate that this works fine, but I want to know if there are any special considerations that I should be aware of.

推荐答案

如果按值传递,将复制闭包对象(假设您未定义内联的lambda,在这种情况下它将被移动)。如果状态的复制成本很高,那么这可能是不希望的,如果状态不可复制,则将无法编译。

If you pass by value you will copy the closure object (assuming you don't define the lambda inline, in which case it will be moved). This might be undesirable if the state is expensive to copy, and will fail to compile if the state is not copyable.

template <class Function>
void higherOrderFunction(Function f);

std::unique_ptr<int> p;
auto l = [p = std::move(p)] {}; // C++14 lambda with init capture
higherOrderFunction(l);         // doesn't compile because l is non-copyable 
                                // due to unique_ptr member
higherOrderFunction([p = std::move(p)] {}); // this still works, the closure object is moved

如果您经过 const 引用,则您不能传递修改其数据成员的可变 lambda作为 higherOrderFunction()的参数 code>,因为可变 lambda具有非< const operator(),则不能在 const 对象上调用它。

If you pass by const reference, then you cannot pass a mutable lambda that modifies its data members as the argument to higherOrderFunction() because a mutable lambda has a non-const operator(), and you cannot invoke that on a const object.

template <class Function>
void higherOrderFunction(Function const& f);

int i = 0;
higherOrderFunction([=]() mutable { i = 0; }); // will not compile

最好的方法是使用转发引用。然后 higherOrderFunction 可以接受调用者传递的左值或右值。

The best option is to use a forwarding reference. Then higherOrderFunction can accept either lvalues or rvalues that the caller passes.

template <class Function>
void higherOrderFunction(Function&& f) {
     std::forward<Function>(f)();
}

这样可以编译简单的情况以及上面提到的情况。有关为什么应使用 std :: forward 的讨论,请参见此答案

This allows the simple cases as well as the ones mentioned above to compile. For a discussion of why std::forward should be used, see this answer.

实时演示

这篇关于我应该通过const引用传递lambda吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆