将返回const引用的lambda存储为std::function时触发段错误
将返回const引用的lambda存储为std::function时触发段错误
这问题我刚看到的时候也愣了一下,仔细抠lambda的返回类型就明白根源在哪了!
你代码里的核心问题出在lambda的自动返回类型推导上:
- 你写的lambda没有显式指定返回类型,编译器会用
auto自动推导返回值类型。这里你return的是静态对象dummy,但auto默认会推导成值类型(也就是const std::vector<int>),而不是你预期的引用类型const std::vector<int>&。 - 这就导致lambda实际上是把
dummy复制了一份,返回这个临时的副本对象。而你的std::function签名要求返回引用,它只能把这个临时副本的引用返回出去。 - 临时对象的生命周期只到
getStuff()调用结束为止,等你在main里拿到vec这个引用时,它指向的临时对象已经被销毁了,此时访问vec.size()自然就触发段错误了。
解决方法
给lambda显式指定返回类型,让它返回引用即可:
#include <vector> #include <functional> class TestClass { public: const std::vector<int> &getStuff() const { return callback(); } protected: // 显式指定lambda返回引用类型 std::function<const std::vector<int> &()> callback = []() -> const std::vector<int>& { static const std::vector<int> dummy; return dummy; }; }; int main() { TestClass test; const auto& vec = test.getStuff(); vec.size(); // 正常运行,不再段错误 return 0; }
或者用decltype(auto)作为lambda的返回类型,它会严格推导返回值的引用属性:
std::function<const std::vector<int> &()> callback = []() -> decltype(auto) { static const std::vector<int> dummy; return dummy; };
这样修改后,lambda返回的就是静态对象dummy的引用,而dummy的生命周期是整个程序运行期间,所以vec引用的是有效对象,访问成员就不会有问题了。
备注:内容来源于stack exchange,提问作者ligazetom
相关产品推荐
相关产品推荐

