我研究了 lambda 并在嵌套 lambda 函数时注意到了一些奇怪的事情。
int x {10}; //assume x has 0x1 address here
cout << "SCOPE: x address: " << &x << endl; //showing 0x1 for x address
auto show = [](int x)
{
cout << "SHOW: x address: " << &x << endl;
};
cout << "SCOPE: show-lambda address: " << &show << endl;
show(x); // showing 0x2 for x address
auto fv = [ x, show]()
{
cout << "FV : x address: " << &x << " " << endl; //0x3
cout << "FV : show-lambda address:" << &show << endl;
show(x); // showing 0x4 for x address
};
auto fr = [&x, show]()
{
cout << "FR : x address: " << &x << " " << endl; //showing 0x1 for x address
cout << "FR : show-lambda address:" << &show << endl;
show(x); //showing 0x4 for x address - WHY???
};
fv();
fr();
我得到的输出是
SCOPE: x address: 0x39f95c
SCOPE: show-lambda address: 0x39f95b
SHOW: x address: 0x39f928
FV : x address: 0x39f950
FV : show-lambda address:0x39f954
SHOW: x address: 0x39f8f8
FR : x address: 0x39f95c
FR : show-lambda address:0x39f948
SHOW: x address: 0x39f8f8
好吧,让我们试着理解这一点。
X 得到地址 a1=0x39f95c
X 按值传递(其值被复制)到 SHOW lambda 中,因此它显示新地址 a2 = 0x39f95b
我们称 FV lambda 按值捕获 X(其值被复制)。所以在 FV 里面它有新地址 a3 = 0x39f950 从 FV 我们调用 SHOW lambda。 X(来自 FV 的范围)按值传递,因此在 SHOW 中我们得到 X 的新地址 - a4 = 0x39f8f8
我们通过引用调用 FR lambda 捕获 X(这里没有值复制)。所以在 FR X 内部有地址 a1 = 0x39f95c - 很公平。 我们从 FR 调用 SHOW lambda。 X(X 引用???)(来自 FV 的范围)按值传递,所以在 SHOW 中我们得到新的...等等什么??? X在这里的地址是0x39f8f8 = a4.
我不明白。据我了解,lambda 被编译为某种类,因此它们是内存中的对象。你可以看到我还在 FV 和 FR 中记录了 SHOW-lambda 地址。他们是不同的。这意味着这些 show-lambda 是不同的对象,因此它们内部的 X 实例应该不同。但它无法让我得出任何结论。
任何人都可以解释我们如何在 SHOW 中的 FR 中获得相同的地址吗?
你期望不同的对象只是最外层范围内
x
的副本是同一个对象。
这是您的代码,使用不同的副本名称:
#include <iostream>
using std::cout;
using std::endl;
int main() {
int x {10};
cout << "SCOPE: x address: " << &x << endl; // this is x
auto show = [](int y)
{
cout << "SHOW: y address: " << &y << endl;
};
cout << "SCOPE: show-lambda address: " << &show << endl;
show(x); // copy x
auto fv = [ z = x, show]() // copy x
{
cout << "FV : z address: " << &z << " " << endl;
show(z); // copy x again
};
auto fr = [&x, show]()
{
cout << "FR : x address: " << &x << " " << endl; // this is x, because captured as reference
show(x); // copy x
};
fv();
fr();
}
在输出中仍然有 3 个不同的
y
因为 show
被调用了 3 次(两次恰好在同一个地址结束,但这只是偶然:
SCOPE: x address: 0x7ffe1f6d067c
SCOPE: show-lambda address: 0x7ffe1f6d067b
SHOW: y address: 0x7ffe1f6d0644
FV : z address: 0x7ffe1f6d0670
SHOW: y address: 0x7ffe1f6d0624
FR : x address: 0x7ffe1f6d067c
SHOW: y address: 0x7ffe1f6d0624