用户想传递副本,但是被封装库阻止了[&]
,这是coliru MCVE:-
#include <iostream>
#include <string>
#include <type_traits>
#include <vector>
#include <functional>
int main(){
std::vector<std::function<void()>> funcs;
for(int n=0;n<3;n++){
auto func=[&,n](){ //[=] for n
std::cout<<""<<n; // user's code
};
//v library (actually inside another utility function)
funcs.push_back([&](){ //user's "n" is blocked ??
//(some library-related code here)
func();
});
//^ library
}
//v library
for(int m=0;m<3;m++){
funcs[m]();
}
}
Run Code Online (Sandbox Code Playgroud)
它打印222
而不是012
。
为什么,以及如何解决呢?
请注意,该库无法了解n
。
根据一个相关的问题(按值捕获c ++ lambda),应正确复制该值。
这是一个做同样事情的更复杂的MCVE,但是可以更好地描述我实际使用它的方式:-
#include <iostream>
#include <string>
#include <type_traits>
#include <vector>
#include <functional>
std::vector<std::function<void()>> libraryStuff;
template<class F>void addToLibrary(F f){
libraryStuff.push_back([&](){ //user's "n" is blocked ??
//some code library related
f();
});
}
void libraryDoNow(){
for(int m=0;m<libraryStuff.size();m++){
libraryStuff[m]();
}
}
int main(){
std::vector<std::function<void()>> funcs;
for(int n=0;n<3;n++){
auto func=[&,n](){
std::cout<<""<<n; // user's code
};
addToLibrary(func);
}
libraryDoNow();
}
Run Code Online (Sandbox Code Playgroud)
您正在func
通过引用捕获funcs.push_back([&](){..};
这会导致悬空的引用,因为func
超出范围的原因是在以后调用它之前:
//v library
for(int n=0;n<3;n++)
funcs[n]();
Run Code Online (Sandbox Code Playgroud)
您需要func
按值捕获局部变量以获取它的副本(并且它包含在n
-value中)。