如何将变量移动到lambda表达式?

时间:2015-03-11 19:19:10

标签: c++ c++11

我看到了lambda表达式的C ++ 11文档(http://en.cppreference.com/w/cpp/language/lambda),支持按值和引用捕获,但不支持rvalue引用。我能找到的最接近的SO问题是:How to capture a unique_ptr into a lambda expression?,但似乎我的用例不需要使用std::bind

代码

#include <iostream>
#include <memory>

class Foo
{
public:
    explicit Foo(int value = 0) : mValue(value) {}

    // The following items are provided just to be explicit
    Foo(Foo &&other) = default;
    Foo &operator=(Foo &&other) = default;
    Foo(const Foo &other) = delete;
    Foo &operator=(const Foo &other) = delete;
    ~Foo() {}

    int mValue;
};

void bar(std::unique_ptr<Foo> f)
{
    std::cout << "bar:  " << std::dec << f->mValue << "\n";
}

int main()
{
    {
        std::unique_ptr<Foo> f(new Foo(22));
        std::cout << "main: " << std::hex << f.get() << "\n";

        // Call the bar function directly (requires using std::move)
        bar(std::move(f));
        std::cout << "main: " << std::hex << f.get() << "\n";
    }

    {
        std::unique_ptr<Foo> f(new Foo(99));
        std::cout << "main: " << std::hex << f.get() << "\n";

        // Lamda expression captures 'f' by reference and then calls the bar function (again, requires using std::move)
        auto fn = [&f](){ bar(std::move(f)); };
        fn(); // Execute the closure
        std::cout << "main: " << std::hex << f.get() << "\n";
    }

    return 0;
}

示例输出

main: 0x92e010
bar:  22
main: 0
main: 0x92e010
bar:  99
main: 0

通过检查输出出现此程序正确运行(即,观察到的结果是我的预期。但是,我有以下问题。

问题

  1. 是否使用等效于直接调用bar函数的代码的闭包?
    • 我明确地问过,因为关于lambda表达式的文档(参见问题的开头)没有说明在捕获的引用上使用std::move的任何内容(即,我想确保这不会发生冲突) undefined behavior或类似的不良结果)。
  2. 如果第一个问题的答案是“你不能在捕获的引用上使用std::move”,那么正确的方法是什么(例如std::bind解决方案等) ?

1 个答案:

答案 0 :(得分:2)

  

使用闭包等效于直接调用bar函数的代码吗?

是的,它们在此代码中具有相同的效果。捕获的引用并不是我能想到的任何特殊方式:只要f在范围内并且可以移动,就可以完全定义行为。