将lambda包装为std::function返回错误结果:模板实参推导的隐患
问题原因
该未定义行为由两处代码问题共同触发:
constant函数返回的lambda返回了指向自身捕获成员的引用constant模板内的lambda按值捕获了参数c,c会作为lambda对象的成员变量存在。而lambda的返回类型声明为const T&,意味着返回的是这个成员变量的引用,该引用的有效性完全依赖lambda对象本身的生命周期,一旦lambda对象被销毁,引用就会悬空。zip的模板推导导致tuple中存储了无意义的引用
调用zip(constant(1.0))时,入参类型是std::function<const double&()>,因此zip的模板参数T被推导为const double&,最终返回的std::function返回值类型为std::tuple<const double&>。
对比good的实现:good使用CTAD推导tuple类型时会自动对引用做decay,得到std::tuple<double>,直接拷贝了引用指向的数值,完全不受引用生命周期的影响。而bad对应的tuple明确存储引用,不会做值拷贝,当访问tuple元素时,引用指向的内存已经因为中间临时对象销毁而失效,最终读到垃圾值。
内容的提问来源于stack exchange,提问作者Sergio Losilla
相关产品推荐
相关产品推荐

