【问题标题】:C++11 lambda capture by copy unless wrapped in std::ref除非包装在 std::ref 中,否则 C++11 lambda 复制捕获
【发布时间】:2018-06-30 05:59:02
【问题描述】:

当将参数传递给std::bind 时,它们总是被复制或移动,除非被 std::ref 包裹并且我想对 lambda 表达式做同样的事情。 问题是,我想将 lambda 表达式的生成包装在一个函数中,并将用户传递的参数转发给 lambda。我想这样做的原因是我想异步调用 lambda 并让用户决定参数是通过引用传递还是通过复制传递。

考虑以下示例。我有以参数为参考的函数print_address。然后我有函数combine_and_call_bind 将参数转发到std::bind

void print_address(int& a) {
  std::cout << "Adress of a = " << &a << std::endl;
}

template<typename F, typename Args>
void combine_and_call_bind(F f, Args&& args) {
  auto a = std::bind(f, std::forward<Args>(args));

  a();
}

用户可以在调用combine_and_call_bind函数时指定参数是复制到std::bind还是通过将参数包装在std::ref中以引用方式传递:

combine_and_call_bind(print_address, a); // copy a into std::bind
combine_and_call_bind(print_address, std::ref(a)); // pass a as reference into std::bind

如何在使用 C++11 时对以下函数 combine_and_call_lambda 执行相同操作?

template<typename F, typename Args>
void combine_and_call_lambda(F f, Args&& args) {
  auto a = [/* std::forward<Args>(args) */, f] {
    f(args);
  };

  a();
}

【问题讨论】:

  • 不相关,但address 是正确的拼写。
  • &amp;? (还有 11 个)
  • @user202729 已编辑;)如果我将变量捕获为&amp;,它只会作为引用传递,或者我可以指定通过复制来捕获它吗?

标签: c++ c++11 lambda stl


【解决方案1】:

您可能会尝试按价值捕获所有内容:

template<typename F, typename... Args>
void combine_and_call_lambda(F f, Args&&... args) {
    auto a = [=]() mutable {
        f(args...);
    };

    a();
}

然后使用:

combine_and_call_lambda(print_address, a);
combine_and_call_lambda(print_address, std::ref(a));

DEMO

我们可以在lambda看到:

captures - 零个或多个捕获的逗号分隔列表,可选 以默认捕获开始。

捕获列表可以按如下方式传递(详见下文 描述):

...

[=] 捕获 lambda 主体中使用的所有自动变量 通过复制和当前对象通过引用(如果存在)

因此,在上面的代码中,所有内容都被复制并存储在 lambda 对象中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-10-22
    • 2016-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多