C++:嵌套lambda函数引用传递参数的相同地址

fivyi3re  于 2023-04-01  发布在  其他
关注(0)|答案(1)|浏览(113)

我学习了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。xx reference?)(来自FV的作用域)是通过值传递的,所以在SHOW内部我们得到新的...等等什么?x的地址在这里是0x39f8f8 = a4
我不明白。据我所知,lambdas被编译为某种类,所以它们是内存中的对象。你可以看到我还记录了FVFR中的SHOW lambda地址。它们是不同的。这意味着这些SHOW lambdas是不同的对象,所以它们内部的x示例应该是不同的。但它不能使我得出任何结论。
有谁能解释一下我们如何在SHOW中获得相同的地址?

vuktfyat

vuktfyat1#

您希望最外层作用域中的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

正如在注解中提到的,打印相同的地址不仅仅是“偶然”。当一个函数返回时,它的堆栈被释放,可以被下一个调用的函数使用。你可以在这个例子中看到同样的效果:

#include <iostream>

void foo() {
    int x = 42;
    std::cout << &x << "\n";
}

int main() {
    foo();
    foo();
}

Possible output

0x7ffddcc6fd9c
0x7ffddcc6fd9c

相关问题