有人会在通过“身份”功能foo1
后解释为什么引用无效吗? A
的“地址”是否传递到foo1
并由struct A {
A(int x) : x_(x) {}
int x_;
};
int main() {
function<const A&(const A& r)> foo1 = [](const A& r) {
return r;
};
vector<A> vec{1, 2, 3};
cout << foo1(vec[0]).x_ << endl; // RUNTIME ERROR
return 0;
}
返回?
const A& r = vec[0];
const A& r1 = r;
问题行与以下内容有何不同:
{{1}}
答案 0 :(得分:43)
问题是你的lambda。它没有做你认为它做的事情:
function<const A&(const A& r)> foo1 = [](const A& r) {
// ~~~~~~
return r;
};
请注意,没有尾随返回类型。这意味着它会自动推断出来。扣除从不为您提供引用类型,因此此lambda返回A
,而不是A const&
。返回的临时A
然后绑定到A const&
function
的返回operator()
。这暂时不是终生延长的。但是当我们完成调用foo1()
时,我们对该临时A
有一个悬空引用。这是未定义的行为,我猜你的编译器会给你一个有用的运行时错误。
要解决此问题,您需要明确指定返回类型:
function<const A&(const A& r)> foo1 = [](const A& r) -> A const& {
return r;
};
但即使这样也很危险,因为您仍然可以将临时 A
传递给此函数并获取悬空引用。没有真正的方法围绕那一个。
陷入此陷阱的容易程度也是LWG Issue 2813
答案 1 :(得分:12)
当您的function
对象返回const A&
时,您提供的lambda不会。它的返回类型是从return语句推导出来的,返回语句推导为A
。尝试添加这样的显式返回类型。
function<const A&(const A& r)> foo1 = [](const A& r) -> const A& {
return r;
};