简体   繁体   English

捕获并移动c ++ 14 lambda表达式中的unique_ptr

[英]Capture and move a unique_ptr in a c++14 lambda expression

I am capturing a unique_ptr in a lambda expression this way: 我正在以这种方式捕获lambda表达式中的unique_ptr:

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

It works great until I try to move capturedStr to another unique_ptr. 它很有效,直到我尝试将capturedStr移动到另一个unique_ptr。 For instance, the following is not working: 例如,以下内容不起作用:

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();

Here is the output from the compiler: 这是编译器的输出:

.../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.

Why isn't it possible to move capturedStr ? 为什么不能移动capturedStr

The operator () of a lambda is const by default, and you can't move from a const object. 默认情况下,lambda的operator ()const ,并且不能从const对象移动。

Declare it mutable if you want to modify the captured variables. 如果要修改捕获的变量,请声明它是mutable

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

To give more detail the compiler is effectively making this transformation: 为了提供更多细节,编译器正在有效地进行这种转换:

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.
    }
}

The use of mutable on the lambda will remove the const from the operator() member function therefore allowing the members to be altered. 在lambda上使用mutable将从operator()成员函数中删除const,从而允许更改成员。

To make the advice more explicit: add mutable : http://coliru.stacked-crooked.com/a/a19897451b82cbbb 为了使建议更明确:添加mutablehttp//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 { };
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM