C++ lambda 捕获这个 vs 通过引用捕获
C++ lambda capture this vs capture by reference
如果我需要生成调用成员函数的lambda,我应该通过引用捕获还是捕获'this'?我的理解是'&'只捕获使用的变量,而'this'捕获所有成员变量。那么最好使用“&”?
class MyClass {
public:
int mFunc() {
// accesses member variables
}
std::function<int()> get() {
//return [this] () { return this->mFunc(); };
// or
//return [&] () { return this->mFunc(); };
}
private:
// member variables
}
捕获this
和引用捕获是两个正交的概念。您可以使用一个、两个或 none。通过引用捕获 this
没有意义,但您可以在通过值捕获 this
的同时通过引用捕获其他变量。
Here 很好地解释了 &
、this
和其他在捕获列表中使用时所指示的内容。
在你的情况下,假设你所要做的就是调用实例的成员函数,该实例实际上被当前正在执行的方法的 this
引用,将 this
在您的捕获列表中应该足够了。
对于您提供的具体示例,您希望通过 this
进行捕获。从概念上讲,通过引用捕获 this
没有多大意义,因为您无法更改 this
的值,您只能将其用作访问 [= 成员的指针32=] 或获取 class 实例的地址。在你的 lambda 函数中,如果你访问隐式使用 this
指针的东西(例如,你调用一个成员函数或访问一个成员变量而不显式使用 this
),编译器将它视为你已经使用this
无论如何。你也可以列出多个捕获,所以如果你想同时捕获成员和局部变量,你可以独立地选择是通过引用还是通过值来捕获它们。以下文章应该让您在 lambda 和捕获方面有一个良好的基础:
https://crascit.com/2015/03/01/lambdas-for-lunch/
此外,您的示例使用 std::function
作为 return 类型,lambda 通过该类型传递回调用方。请注意,std::function
并不总是像您想象的那么便宜,因此如果您能够直接使用 lambda 而不是必须将其包装在 std::function
中,它可能会更有效率。以下文章虽然与您的原始问题没有直接关系,但可能仍会为您提供一些与 lambda 和 std::function
相关的有用 material(请参阅 存储函数对象的替代方法部分,但总的来说这篇文章可能会让人感兴趣):
这不是一个明确的情况。相反,两者(至少可能)完成的事情略有不同。例如,考虑这样的代码:
#include <iostream>
class foo {
int bar = 0;
public:
void baz() {
int bar = 1;
auto thing1 = [&] { bar = 2; };
auto thing2 = [this] { this->bar = 3; };
std::cout << "Before thing1: local bar: " << bar << ", this->bar: " << this->bar << "\n";
thing1();
std::cout << "After thing1: local bar: " << bar << ", this->bar: " << this->bar << "\n";
thing2();
std::cout << "After thing2: local bar: " << bar << ", this->bar: " << this->bar << "\n";
}
};
int main() {
foo f;
f.baz();
}
如您所见,捕获this
仅捕获可以通过this
引用的变量。在这种情况下,我们有一个局部变量来隐藏实例变量(是的,这通常是个坏主意,但在这种情况下,我们使用它来显示每个实例的部分功能)。正如我们在 运行 程序中看到的那样,捕获 this
与通过引用隐式捕获得到不同的结果:
Before thing1: local bar: 1, this->bar: 0
After thing1: local bar: 2, this->bar: 0
After thing2: local bar: 2, this->bar: 3
关于捕获所有内容与仅捕获您使用的内容的具体细节:两者都不会捕获您不使用的任何变量。但是,由于 this
是一个指针,捕获该变量可以让您访问它指向的所有内容。不过,这并不是 this
独有的。捕获任何指针将使您可以访问它指向的任何内容。
如果我需要生成调用成员函数的lambda,我应该通过引用捕获还是捕获'this'?我的理解是'&'只捕获使用的变量,而'this'捕获所有成员变量。那么最好使用“&”?
class MyClass {
public:
int mFunc() {
// accesses member variables
}
std::function<int()> get() {
//return [this] () { return this->mFunc(); };
// or
//return [&] () { return this->mFunc(); };
}
private:
// member variables
}
捕获this
和引用捕获是两个正交的概念。您可以使用一个、两个或 none。通过引用捕获 this
没有意义,但您可以在通过值捕获 this
的同时通过引用捕获其他变量。
Here 很好地解释了 &
、this
和其他在捕获列表中使用时所指示的内容。
在你的情况下,假设你所要做的就是调用实例的成员函数,该实例实际上被当前正在执行的方法的 this
引用,将 this
在您的捕获列表中应该足够了。
对于您提供的具体示例,您希望通过 this
进行捕获。从概念上讲,通过引用捕获 this
没有多大意义,因为您无法更改 this
的值,您只能将其用作访问 [= 成员的指针32=] 或获取 class 实例的地址。在你的 lambda 函数中,如果你访问隐式使用 this
指针的东西(例如,你调用一个成员函数或访问一个成员变量而不显式使用 this
),编译器将它视为你已经使用this
无论如何。你也可以列出多个捕获,所以如果你想同时捕获成员和局部变量,你可以独立地选择是通过引用还是通过值来捕获它们。以下文章应该让您在 lambda 和捕获方面有一个良好的基础:
https://crascit.com/2015/03/01/lambdas-for-lunch/
此外,您的示例使用 std::function
作为 return 类型,lambda 通过该类型传递回调用方。请注意,std::function
并不总是像您想象的那么便宜,因此如果您能够直接使用 lambda 而不是必须将其包装在 std::function
中,它可能会更有效率。以下文章虽然与您的原始问题没有直接关系,但可能仍会为您提供一些与 lambda 和 std::function
相关的有用 material(请参阅 存储函数对象的替代方法部分,但总的来说这篇文章可能会让人感兴趣):
这不是一个明确的情况。相反,两者(至少可能)完成的事情略有不同。例如,考虑这样的代码:
#include <iostream>
class foo {
int bar = 0;
public:
void baz() {
int bar = 1;
auto thing1 = [&] { bar = 2; };
auto thing2 = [this] { this->bar = 3; };
std::cout << "Before thing1: local bar: " << bar << ", this->bar: " << this->bar << "\n";
thing1();
std::cout << "After thing1: local bar: " << bar << ", this->bar: " << this->bar << "\n";
thing2();
std::cout << "After thing2: local bar: " << bar << ", this->bar: " << this->bar << "\n";
}
};
int main() {
foo f;
f.baz();
}
如您所见,捕获this
仅捕获可以通过this
引用的变量。在这种情况下,我们有一个局部变量来隐藏实例变量(是的,这通常是个坏主意,但在这种情况下,我们使用它来显示每个实例的部分功能)。正如我们在 运行 程序中看到的那样,捕获 this
与通过引用隐式捕获得到不同的结果:
Before thing1: local bar: 1, this->bar: 0
After thing1: local bar: 2, this->bar: 0
After thing2: local bar: 2, this->bar: 3
关于捕获所有内容与仅捕获您使用的内容的具体细节:两者都不会捕获您不使用的任何变量。但是,由于 this
是一个指针,捕获该变量可以让您访问它指向的所有内容。不过,这并不是 this
独有的。捕获任何指针将使您可以访问它指向的任何内容。