【问题标题】:What is the advantage of storing a lambda in a `std::function` as opposed to an `auto variable`?与 `auto variable` 相比,将 lambda 存储在`std::function` 中的优势是什么?
【发布时间】:2018-11-07 23:52:57
【问题描述】:

将 lambda 存储在 std::functionauto variable 相比有什么优势。例如,在下面的代码中,我将 lambda 存储在 variable f1 而不是 std::function f

#include <iostream>
#include <functional>
using namespace std;

void global_f() {
    cout << "global_f()" << endl;
}

struct Functor {
    void operator()() { cout << "Functor" << endl; }
};

int main() {
    std::function<void()> f;

    cout << "sizeof(f) == " << sizeof(f) << endl;

    f = global_f;
    f();

    auto f1 = [](){ cout << "Lambda" << endl;};
    f1();

    Functor functor;
    f = functor;
    f();
}

【问题讨论】:

  • 您可能会或可能不会提高性能,具体取决于 lambda,因为 std::function 已被擦除。
  • 没有优势,但有时你不知道你是否得到一个 lambda 或其他一些可调用的,std::function 可以包装的不仅仅是 lambdas
  • 如果你想存储一个函数对象并且你希望它有一个特定的签名是留给std::function的少数用例之一。
  • @user463035818 闭包类型显式删除分配。一个 lambda 类型可以有多个值,例如,如果你从一个自动函数返回它,它们可以捕获不同的值
  • @user463035818 例如auto make = [](int val){ return [val](){ std::cout &lt;&lt; val; } }; auto one = make(1); 添加one = make(1); 会编译失败

标签: c++ lambda std-function


【解决方案1】:

在您的简单示例中,将 lambda 存储在 std::function 中没有任何好处。通常,使用auto 存储 lambda 会更有效,但也有很大的限制。 auto 版本只能用作局部变量。如果要存储 lambda 供以后使用,则必须使用 std::function

例如,您可能希望将 lambda 存储在类成员中。考虑以下类:

class Foo
{
  std::function<void()> callback_;
public:
  void Bar(int value)
  {
    callback_ = [value] { DoStuff(value); }
  }
  /* other constructors and methods omitted */
}

在这种情况下,您不能使用 auto,因为 lambda 的类型是匿名的,并且只能在 Bar 方法中使用。

std::function 在您想使用 lambda 作为常规函数的参数时也很有用。该函数无法知道 lambda 的类型,但它可以声明一个 std::function 参数。例如:

void Foo(std::function<void()> callback);

...

Foo([](){ cout << "Lambda" << endl;});

值得指出的是,这不适用于函数模板。在这种情况下使用 lambda 时,最好让编译器推断 lambda 的类型(类似于使用auto)。例如:

template <class F> void Foo(F&& callback) { /* details */ }

...

Foo([](){ cout << "Lambda" << endl;}

【讨论】:

  • 对不起,我不同意你的观点。如果可能,您可以将 lambda 传递给函数 template &lt;typename F&gt; void Foo(F f) 比使用 std::function 更可取。我也不太明白“如果你想存储 lambda 供以后使用,那么你必须使用 std::function”是什么意思
  • 我会详细说明你的第二点。正如我所提到的,在将 lambda 传递给 函数(而不是函数模板)时,您需要 std::function
  • 当我将我的foo 称为foo ( [](){} ) 时,foo 是一个函数而不是函数模板。 Afaik 你不能调用函数模板
  • @user463035818: "如果可能" 当它不可能可能时会发生什么?特定功能可能无法成为模板的原因有很多。不仅如此,模板版本不能带成员指针。
  • @NicolBolas 自从我发表评论以来,答案包含更多细节。之前的论点大致是:“当你想将 lambda 传递给函数时,你需要 std::function”,这并没有真正说服我。 (现在它得到了我的支持)
猜你喜欢
  • 2016-07-03
  • 2011-11-27
  • 1970-01-01
  • 2012-08-21
  • 2016-07-04
  • 2011-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多