C++中Lambda捕获this返回数据成员引用为何触发段错误?
段错误原因分析与解决方法
问题现象
以下代码在执行std::string k = a.handler_.get_info().a;时触发段错误,且执行std::cout << &a.handler_.get_info();输出0(实际为返回的引用指向已销毁对象的无效地址):
#include <functional> #include <string> #include <iostream> struct Info { std::string a{"abc"}; }; struct Handlers { std::function<const Info&()> get_info; }; class A { public: A() { handler_ = Handlers{ .get_info = [this](){return data;} }; }; Info data; Handlers handler_; }; int main() { A a; std::string k = a.handler_.get_info().a; std::cout << k; }
编译环境:g++ (Ubuntu 12.2.0-3ubuntu1) 12.2.0,编译命令g++ main.cpp --std=c++2a
错误原因
- Lambda返回值类型不匹配导致悬挂引用:
std::function的签名是const Info&(),要求返回Info的const引用,但你定义的lambda[this](){return data;}中,data是Info类型成员,return data会返回临时值拷贝,而非引用。调用get_info()时,临时Info对象会被绑定到const Info&上,但临时对象在函数调用结束后立即销毁,后续访问其a成员时,引用已悬空,直接触发段错误。 - 你看到的输出0是因为访问了已销毁临时对象的地址,属于无效内存地址的表现。
解决方法
修正lambda的返回逻辑,让它返回data的有效const引用,两种可行方式:
方式一:显式指定lambda返回类型
A() { handler_ = Handlers{ .get_info = [this]() -> const Info& { return data; } }; }
方式二:使用std::cref返回引用
#include <functional> // std::cref 需要包含此头 A() { handler_ = Handlers{ .get_info = [this]() { return std::cref(data); } }; }
修正后,get_info()返回的是A::data的有效const引用,访问其a成员时不会出现悬空引用,段错误即可修复。
内容的提问来源于stack exchange,提问作者Harry Check
相关产品推荐
相关产品推荐

