C++ 参考捕获与移动捕获,Lambdas
我对通过引用将变量传递到lambda(1)和将其移动到捕获列表中的lambda(2)之间的区别感到困惑。两者都产生相同的结果,但我不确定使用其中一种/或的含义是什么(因此,什么是最佳实践?)C++ 参考捕获与移动捕获,Lambdas,c++,pointers,lambda,C++,Pointers,Lambda,我对通过引用将变量传递到lambda(1)和将其移动到捕获列表中的lambda(2)之间的区别感到困惑。两者都产生相同的结果,但我不确定使用其中一种/或的含义是什么(因此,什么是最佳实践?) #包括 #包括 #包括 使用std::cout; 使用std::使_唯一; int main(){ 自动p=使_唯一(500); 自动lambda=[&p](){ cout如果您通过引用捕获,那么lambda的捕获的ptr只引用p,因此当您调用lambda()时,对p的更改将反映出来。一种简单的方法是在运行
#包括
#包括
#包括
使用std::cout;
使用std::使_唯一;
int main(){
自动p=使_唯一(500);
自动lambda=[&p](){
cout如果您通过引用捕获,那么lambda的捕获的ptr
只引用p,因此当您调用lambda()
时,对p的更改将反映出来。一种简单的方法是在运行lambda之前重新分配p
p.reset(new int(100));
lambda();
通过引用捕获时,lambda现在将打印100。通过移动捕获,lambda仍然打印500,因为它保留着原始的unique_ptr,直到lambda
超出范围后才会删除
相反,使用移动捕获时,您已将指针移出p
,因此在为p
指定新值之前取消引用p
是无效的。如果在创建lambda后尝试取消引用p,您可能会看到运行时错误。显然,它们是不同的
为了实际理解差异和含义,我们可以用struct
进行类比
参考Lambda
以下是lambda:
auto lambda = [&p]() {
cout << "Inside the lambda -- value = " << *p << '\n';
};
auto lambda = [ptr = std::move(p)]() {
cout << "Inside the lambda -- value = " << *ptr << '\n';
};
因此,在构造lambda时,对std::unique_ptr
的引用将存储在lambda本身中。这可能会导致很大的影响:引用的对象(p
)不属于lambda
例如,在这种情况下,您必须关心lambda之外的p
的活跃度,以避免出现诸如悬挂引用之类的问题
例如:
int main() {
auto p = make_unique<int>(500);
auto lambda = [&p]() {
cout << "Inside the lambda -- value = " << *p << '\n';
};
p.reset(); // p has been reset here!!! The pointer is NULL!
lambda(); // Undefined Behaviour here. Because lambda will call *p inside which is null!
}
正如您所看到的,场景现在完全不同了,“内部”变量(ptr
)不再是参考
在这种情况下,lambda将在其构造期间获得指针的所有权。遵循std::move
背后的逻辑就像lambda“窃取”资源一样
因此,在lambda构造之后,p
(主main
的局部变量)和ptr
(lambda的内部变量)之间不再存在相关性。它们是两个不同的独立对象
实际上:
int main() {
auto p = make_unique<int>(500);
auto lambda = [ptr = std::move(p)]() {
cout << "Inside the lambda -- value = " << *ptr << '\n';
};
// now p (the local variable of main) is null because lambda stole it!
assert(p == nullptr); // !!!!
// here you can even reassign p. The object inside lambda is another object.
lambda();
}
int main(){
自动p=使_唯一(500);
自动lambda=[ptr=std::move(p)](){
所示的示例都不能将任何变量传递到lamba中。lamba函数没有参数。它们所显示的是lambda通过值或引用捕获变量。这与将某个变量作为参数传递给lambda有根本性的区别,您应该首先关注理解其区别。Thanks,这是一个重要的区别。传球会发生在括号内。
int main() {
auto p = make_unique<int>(500);
auto lambda = [&p]() {
cout << "Inside the lambda -- value = " << *p << '\n';
};
p.reset(); // p has been reset here!!! The pointer is NULL!
lambda(); // Undefined Behaviour here. Because lambda will call *p inside which is null!
}
auto lambda = [ptr = std::move(p)]() {
cout << "Inside the lambda -- value = " << *ptr << '\n';
};
struct __lambda_move {
__lambda_reference(std::unique_ptr<int> p): ptr(p) {}
void operator()() const {
std::cout << "Inside the lambda -- value = " << *(this->ptr) << '\n';
}
private:
std::unique_ptr<int> ptr;
};
auto lambda = __lambda_move(std::move(p));
int main() {
auto p = make_unique<int>(500);
auto lambda = [ptr = std::move(p)]() {
cout << "Inside the lambda -- value = " << *ptr << '\n';
};
// now p (the local variable of main) is null because lambda stole it!
assert(p == nullptr); // !!!!
// here you can even reassign p. The object inside lambda is another object.
lambda();
}