C++ g+中的lambda bug中的自动+-5.

C++ g+中的lambda bug中的自动+-5.,c++,C++,下面的代码包含两个相同的lambda,但使用g++5编译时会产生不同的答案。在参数声明中使用auto关键字的lambda编译良好,但返回零而不是正确的计数1。为什么?我应该添加代码,使用g++-6生成正确的输出 g++-5 -std=c++14 file.cc ./a.out Output: f result=0 (incorrect result from lambda f) ... g result=1 (correct result from lambda g) ... #inclu

下面的代码包含两个相同的lambda,但使用g++5编译时会产生不同的答案。在参数声明中使用auto关键字的lambda编译良好,但返回零而不是正确的计数1。为什么?我应该添加代码,使用g++-6生成正确的输出

g++-5 -std=c++14 file.cc
./a.out
Output:
f result=0  (incorrect result from lambda f)
...
g result=1  (correct result from lambda g)
...

#include<iostream>
#include<set>
#include<vector>
#include<algorithm>
using namespace std;

enum obsMode { Hbw, Lbw, Raw, Search, Fold};

int main(int , char **)
{
    static set<obsMode> legal_obs_modes = {Hbw, Lbw, Raw, Search, Fold};
    vector<obsMode> obs_mode = { Hbw,Lbw,Hbw,Lbw};
    // I named the lambdas to illustrate the issue 
    auto f =    [&] (auto i) -> void
        {
            cout << "f result=" << legal_obs_modes.count(i) << endl;
        };
    auto g =    [&] (obsMode i) -> void
        {
            cout << "g result=" << legal_obs_modes.count(i) << endl;
        };
    // f does not work
    for_each(obs_mode.begin(), obs_mode.end(), f);
    // g does work
    for_each(obs_mode.begin(), obs_mode.end(), g);
    return 0;
}
g++-5-std=c++14 file.cc
/a.out
输出:
f结果=0(lambda f的结果不正确)
...
g结果=1(lambda g的正确结果)
...
#包括
#包括
#包括
#包括
使用名称空间std;
枚举obsMode{Hbw,Lbw,Raw,Search,Fold};
int main(int,char**)
{
静态设置合法的obs模式={Hbw、Lbw、Raw、搜索、折叠};
向量obs_模式={Hbw,Lbw,Hbw,Lbw};
//我命名lambdas来说明这个问题
自动f=[&](自动i)->void
{

cout对这个问题稍微深入一点就可以看出问题所在

它似乎从5.1一直存在到6.1(根据),我注意到这可能是相关的。错误代码是:

#include <iostream>
#include <functional>
int main() {
    static int a;
    std::function<void(int)> f = [](auto) { std::cout << a << '\n'; };
    a = 1;
    f(0);
}
然后您将看到一些非常有趣的内容(为了可读性,我重新格式化了一些内容):

失败的
f
one的大小是零而不是五,并且地址完全不同。零大小足以表明
count
将返回零,原因很简单,因为在一个空集中没有元素。我怀疑不同的地址是链接的bug报告中涉及的相同问题的表现

实际上,您可以在
编译器资源管理器
汇编程序输出中看到这一点,其中两个不同的lambda加载不同的设置地址:

mov    edi, 0x605260 ; for f
mov    edi, 0x605220 ; for g
设置为自动而不是静态会导致问题完全消失。lambda内部和外部的地址都相同,
0x7ffd808eb050
(在堆栈上而不是在静态区域,因此值发生了巨大变化)。这往往与这样一个事实结合在一起,即静力学实际上并没有在lambdas中捕获,因为它们总是应该位于同一地址,所以可以按原样使用

因此,问题似乎在于
f
lambda及其
auto
-推导的参数正在复制静态数据,而不是就地使用。我不是指一个好的副本,我指的是一个类似于2017年某个时候用完墨粉的照片复印机的副本:-)

因此,在回答您关于这是否是一个bug的具体问题时,我认为大家的一致意见应该是肯定的。

“fails”是一个糟糕的错误描述。请显示您得到的输出,并解释它与您的期望有何不同显示lambda“fail”?此外(如果这是编译器bug的情况,g++5是旧的),准确显示如何编译以及g的版本和目标++
0x605220 5

0x605260 0 f result=0
0x605260 0 f result=0
0x605260 0 f result=0
0x605260 0 f result=0

0x605220 5 g result=1
0x605220 5 g result=1
0x605220 5 g result=1
0x605220 5 g result=1
mov    edi, 0x605260 ; for f
mov    edi, 0x605220 ; for g