【问题标题】:Capture and move a unique_ptr in a c++14 lambda expression在 c++14 lambda 表达式中捕获和移动 unique_ptr
【发布时间】:2015-03-04 05:26:35
【问题描述】:

我以这种方式在 lambda 表达式中捕获 unique_ptr:

auto str = make_unique<string>("my string");
auto lambda = [ capturedStr = std::move(str) ] {
   cout << *capturedStr.get() << endl;
};
lambda();

在我尝试将 capturedStr 移动到另一个 unique_ptr 之前,它工作得很好。例如,以下内容不起作用:

auto str = make_unique<string>("my string");
auto lambda = [ capturedStr = std::move(str) ] {
    cout << *capturedStr.get() << endl;
    auto str2 = std::move(capturedStr); // <--- Not working, why?
};
lambda();

这是编译器的输出:

.../test/main.cpp:11:14: error: call to implicitly-deleted copy
constructor of 'std::__1::unique_ptr<std::__1::basic_string<char>,
std::__1::default_delete<std::__1::basic_string<char> > >'
        auto str2 = std::move(capturedStr);
             ^      ~~~~~~~~~~~~~~~~~~~~~~ ../include/c++/v1/memory:2510:31: note: copy constructor is implicitly
deleted because 'unique_ptr<std::__1::basic_string<char>,
std::__1::default_delete<std::__1::basic_string<char> > >' has a
user-declared move constructor
    _LIBCPP_INLINE_VISIBILITY unique_ptr(unique_ptr&& __u) _NOEXCEPT
                              ^ 1 error generated.

为什么不能移动capturedStr

【问题讨论】:

  • Lambdas' operator ()const,除非它被声明为 mutable,并且你不能从 const 对象中移动。
  • 谢谢@T.C.,你能写一个答案吗,我会接受的

标签: c++ c++11 lambda c++14


【解决方案1】:

lambda 的operator () 默认为const,您不能从const 对象移动。

如果要修改捕获的变量,请声明mutable

auto lambda = [ capturedStr = std::move(str) ] () mutable {
//                                             ^^^^^^^^^^
    cout << *capturedStr.get() << endl;
    auto str2 = std::move(capturedStr);
};

【讨论】:

  • 我以为你不会发帖 :) +1
【解决方案2】:
auto lambda = [ capturedStr = std::move(str) ] {
   cout << *capturedStr.get() << endl;
   auto str2 = std::move(capturedStr); // <--- Not working, why?
};

为了提供更多细节,编译器正在有效地进行这种转换:

class NameUpToCompiler
{
    unique_ptr<string> capturedStr;  // initialized from move assignment in lambda capture expression

    void operator()() const
    {
        cout << *capturedStr.get() << endl;
        auto str2 = std::move(capturedStr);  // move will alter member 'captureStr' but can't because of const member function.
    }
}

在 lambda 上使用 mutable 将从 operator() 成员函数中删除 const,因此允许更改成员。

【讨论】:

    【解决方案3】:

    为了使建议更明确:添加mutable:http://coliru.stacked-crooked.com/a/a19897451b82cbbb

    #include <memory>
    
    int main()
    {
        std::unique_ptr<int> pi(new int(42));
    
        auto ll = [ capturedInt = std::move(pi) ] () mutable { };
    }
    

    【讨论】:

      猜你喜欢
      • 2012-01-04
      • 1970-01-01
      • 2015-08-12
      • 2016-01-30
      • 2015-11-23
      • 1970-01-01
      • 2019-11-29
      • 2018-03-15
      相关资源
      最近更新 更多