Lambda expression is a new introduction to C++11, which brings us a lot of convenience and makes the code simple and clear.
But when we combine unique_ptr and lambda expressions, errors tend to occur and are fatal.
Look directly at the following code:
#include "stdafx.h"#include <memory>#include <vector>#include <algorithm>classMessage { Public: Message () {}};intMainintargcChar* argv[]) {STD:: Vector<std::unique_ptr<message>>messages; for(inti =0; I < +; i++) {STD::unique_ptr<message> testmess; Messages.push_back (STD:: Move (testmess)); }STD:: For_each (Messages.begin (), Messages.end (), [] (STD::unique_ptr<message> testmess) {//do something stupid});return 0;}
Unfortunately, this code compilation produces errors, but it's also lucky:
d: \program Files (x86) \ Microsoft Visual Studio 14.0 \vc\include \ Algorithm (24 ) : Error c2280 : "STD: :unique_ptr<message , STD: :d Efault_delete<_ty>> : :unique_ptr (const STD: :unique_ptr<_ty , STD: :d Efault_delete<_ty>> &)" attempt to reference a deleted function
Simple analysis
What we use in lambda expressions is pass-by-value;
Passing by value produces a copy, which produces a unique_ptr copy;
But we know that this is obviously a mistake.
The workaround is simply to pass by reference instead by pointer:
#include <iostream>#include <memory>#include <vector>#include <algorithm>classMessage { Public: Message () {}};intMainintargcChar* argv[]) {STD:: Vector<std::unique_ptr<message>>messages; for(inti =0; I < +; i++) {STD::unique_ptr<message> testmess; Messages.push_back (STD:: Move (testmess)); }STD:: For_each (Messages.begin (), Messages.end (), [] (STD::unique_ptr<message> &testmess) {//do something stupid});return 0;}
The above content is just an appetizer, what if we want to capture unique_ptr in a lambda expression?
Write down the following code very gracefully:
#include<iostream>#include<memory>#include<string>int main(){ autostd::make_unique<std::string>("my string"); autostd::move(str)]{ std::coutstd::endl; }; lambda(); return0;}
Everything is perfect, compile and run the output correctly.
Next, do something more:
#include <iostream>#include <memory>#include <string>intMain () {Autostr =STD::make_unique<STD::string> ("My string");AutoLambda = [CAPTUREDSTR =STD:: Move (str)] {STD::cout<< *capturedstr.get () <<STD:: Endl;AutoSTR2 =STD:: Move (CAPTUREDSTR);STD::cout<< *STR2 <<STD:: Endl; }; Lambda ();return 0;}
Congratulations, compilation error.
What is the reason? Why Auto str2 = Std::move (CAPTUREDSTR);
This is the knowledge of lambda expressions:
The lambda expression is const by default, and we certainly cannot std::move a const object.
The solution is also very simple, is to add the keyword mutable
The program is as follows and is running intact:
#include <iostream>#include <memory>#include <string>intMain () {Autostr =STD::make_unique<STD::string> ("My string");AutoLambda = [CAPTUREDSTR =STD:: Move (str)] ()mutable{STD::cout<< *capturedstr.get () <<STD:: Endl;AutoSTR2 =STD:: Move (CAPTUREDSTR);STD::cout<< *STR2 <<STD:: Endl; }; Lambda ();return 0;}
Smart pointer unique_ptr series in combat C + +-Unique_ptr with lambda error (especially capturing unique_ptr in lambda)