代码之家  ›  专栏  ›  技术社区  ›  Serge

lambda函数中的变量捕获是否允许是静态数据结构的成员?

c++
  •  1
  • Serge  · 技术社区  · 6 年前

    我截取了下面的代码。

    bool parseTool() {
       string name;
       string version;
       static /*!!*/ AttrMap attrMap = {
           {"name", Attr([&](const string &val)->bool{name = val;return true;})},
           {"version", Attr([&](const string &val)->bool{version = val;return true;})},
       };
       return parseAttributes(attrMap);
    }
    

    attrmap声明为static,lambda函数从parsetool的堆栈捕获变量。

    编译不会产生错误,可执行文件在开始产生垃圾时运行得很愉快。当然,删除“static”可以修复“trash”问题(可能使name和version static也可以修复它,但我还没有尝试过)。我不明白编译器在这种情况下捕获什么 attrMap 已初始化。

    问题是,编译器为什么不抱怨呢?标准中有什么东西可以标记这个案子(我找不到)?编译器在那里做什么?

    我在Linux上运行gcc-7.2.8和-std=c++17。

    1 回复  |  直到 6 年前
        1
  •  2
  •   Alan Birtles    6 年前

    编译器无法知道您捕获的引用在下次调用lambda时将不再有效,甚至无法知道lamda将再次调用。

    您发布的代码是危险的,可能会失败,但根据标准是完全有效的,因此编译器可以在没有警告的情况下自由接受它。

    要修复此问题,请按值捕获变量或使lambda不是静态的。使lambda静态化可能没有多大意义,因为在大多数实现中创建lambda可能并不昂贵,而且取决于lambda的使用方式可能完全内联。