我截取了以下代码。
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被声明为静态,lambda函数从parseTool的堆栈中捕获变量。
当编译开始产生垃圾时,编译不会产生错误,并且可执行文件运行得很愉快。当然,删除"static"可以修复"trash"问题(可能将名称和版本设置为static也会修复它,但我还没有尝试过(。我不明白在这种情况下,当静态attrMap
初始化时,编译器会捕获什么。
问题是,编译器为什么不抱怨呢?标准中有什么东西可以标记这个案例吗(我找不到(?编译器在那里做什么?
我在linux上用-std=c++17运行gcc-7.2.8。
编译器无法知道您捕获的引用在下次调用lambda时将不再有效,甚至无法知道是否会再次调用lamda。
你发布的代码很危险,很可能会失败,但根据标准,它是完全有效的,所以编译器可以自由接受它,而不会发出警告。
若要修复它,请按值捕获变量或使lambda不是静态的。使lambda为静态可能没有多大意义,因为在大多数实现中创建lambda可能并不昂贵,并且取决于lambda的使用方式可能会完全内联。