gpt4 book ai didi

c++ - Lambda函数可变捕获从引用到全局变量的行为差异

转载 作者:行者123 更新时间:2023-12-01 08:54:06 28 4
gpt4 key购买 nike

我发现如果我使用lambda使用mutable关键字捕获对全局变量的引用,然后修改lambda函数中的值,则结果在编译器之间是不同的。

#include <stdio.h>
#include <functional>

int n = 100;

std::function<int()> f()
{
int &m = n;
return [m] () mutable -> int {
m += 123;
return m;
};
}

int main()
{
int x = n;
int y = f()();
int z = n;

printf("%d %d %d\n", x, y, z);
return 0;
}

VS 2015和GCC的结果(g++(Ubuntu 5.4.0-6ubuntu1〜16.04.12)5.4.0 20160609):
100 223 100

来自clang++(clang版本3.8.0-2ubuntu4(标签/RELEASE_380/final))的结果:
100 223 223

为什么会这样? C++标准允许吗?

最佳答案

Lambda无法通过值本身捕获引用(为此,请使用std::reference_wrapper)。

在您的lambda中,[m]按值捕获m(因为捕获中没有&),因此首先取消引用m(作为n的引用),并捕获其引用的对象的副本(n)。这与这样做没有什么不同:

int &m = n;
int x = m; // <-- copy made!

然后,lambda修改该副本,而不是原始副本。正如您所预期的,这就是您在VS和GCC输出中看到的。

Clang输出错误,如果尚未输出,则应将其报告为错误。

如果您想让lambda修改 n,请改为通过引用捕获 m: [&m]。这与将一个引用分配给另一个引用没有什么不同,例如:

int &m = n;
int &x = m; // <-- no copy made!

或者,您可以完全摆脱 m并通过引用捕获 n: [&n]

尽管由于 n在全局范围内,所以实际上根本不需要捕获它,但是lambda可以全局访问它而无需捕获它:
return [] () -> int {
n += 123;
return n;
};

关于c++ - Lambda函数可变捕获从引用到全局变量的行为差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60878566/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com