2015-01-06 109 views
25

我這樣捕獲的unique_ptr在lambda表達式移動的unique_ptr:捕獲和在C++ 14 lambda表達式

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

+11

Lambdas'operator()'是'const',除非它被聲明爲'mutable',並且你不能從'const'對象移動。 –

+1

謝謝@ T.C。,你能寫一個答案,我會接受它 – MartinMoizard

回答

45

默認情況下,lambda的operator()const,並且不能從const對象移動。如果您想修改捕獲的變量,則聲明mutable

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

我以爲你不會發布:) +1 – sehe

6
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,因此a讓成員被改變。