In practice, the intelligent pointer unique_ptr series in c ++ -- the combination of unique_ptr and lambda errors (especially capturing unique_ptr in lambda)
Lambda expressions are newly introduced in C ++ 11, which brings us a lot of convenience and makes the code concise and clear.
But when we combine unique_ptr with lambda expressions, errors often occur and are fatal.
Take a look at the following code:
#include "stdafx.h"#include
#include
#include class Message {public: Message() {}};int main(int argc, char* argv[]){ std::vector
>messages; for (int i = 0; i < 1000; i++) { std::unique_ptr
testMess; messages.push_back(std::move(testMess)); } std::for_each(messages.begin(), messages.end(), [](std::unique_ptr
testMess) { // do something stupid }); return 0;}
However, unfortunately, this code compilation will produce errors, but it is also lucky:
D: \ program files (x86) \ microsoft visual studio 14.0 \ vc \ include \ algorithm (24): error C2280: "std: unique_ptr
>:: Unique_ptr (const std: unique_ptr <_ Ty, std: default_delete <_ Ty> &) ": attempts to reference the deleted Function
Simple Analysis
In lambda expressions, we use value-based transmission;
By value transfer, a copy will be generated, and a unique_ptr copy will be generated;
But we know that this is obviously a mistake.
The solution is simple, that is, pass by reference instead of pass by pointer:
#include
#include
#include
#include class Message {public: Message() {}};int main(int argc, char* argv[]){ std::vector
>messages; for (int i = 0; i < 1000; i++) { std::unique_ptr
testMess; messages.push_back(std::move(testMess)); } std::for_each(messages.begin(), messages.end(), [](std::unique_ptr
&testMess) { // do something stupid }); return 0;}
The above content is just an appealer. What if we want to capture unique_ptr in lambda expressions?
Write the following code elegantly:
#include
#include
#include
int main(){ auto str = std::make_unique
("my string"); auto lambda = [capturedStr = std::move(str)]{ std::cout << *capturedStr.get() << std::endl; }; lambda(); return 0;}
Everything is perfect, and the compiling and running outputs are correct.
Next, let's do something:
#include
#include
#include
int main(){ auto str = std::make_unique
("my string"); auto lambda = [capturedStr = std::move(str)] { std::cout << *capturedStr.get() << std::endl; auto str2 = std::move(capturedStr); std::cout << *str2 << std::endl; }; lambda(); return 0;}
Congratulations, compilation error.
Why? Why is auto str2 = std: move (capturedStr); incorrect?
This is the knowledge of lambda expressions:
Lambda expressions are const by default. We certainly cannot use std: move a const object.
The solution is simple, that is, adding keywordsMutable
The program is running as follows:
#include
#include
#include
int main(){ auto str = std::make_unique
("my string"); auto lambda = [capturedStr = std::move(str)] ()mutable { std::cout << *capturedStr.get() << std::endl; auto str2 = std::move(capturedStr); std::cout << *str2 << std::endl; }; lambda(); return 0;}