2017-02-10 41 views
33

有人会解释为什么参考经过“身份”功能后失效,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; 
+0

我试着用vs2015和你的代码工作得很好。 – alangab

+0

@alangab在VS2013中没有工作。 –

+8

我以为lambda被称为'傻瓜'。那是愚蠢的。 –

回答

43

问题是你的lambda。它不会做你认为它的做法:

function<const A&(const A& r)> foo1 = [](const A& r) { 
//            ~~~~~~ 
    return r; 
}; 

请注意,没有结尾返回类型。这意味着它会自动推断出来。扣除永远不会给你一个参考类型,所以这个lambda返回一个A,而不是A const&。返回的临时A然后绑定到返回A const&functionoperator()。这个临时并非终身延长。但是,当我们完成呼叫foo1()的时候,我们有一个暂时的参考A。这是未定义的行为,我想你的编译器给了你一个有用的运行时错误。

要解决这个问题,你需要明确指定返回类型:

function<const A&(const A& r)> foo1 = [](const A& r) -> A const& { 
    return r; 
}; 

但是,即使这是很危险的,因为你还可以通过一个临时A到这个功能,并得到一个悬空的参考了。没有真正的方式围绕那一个。


的难易掉入这个陷阱的也LWG Issue 2813

+4

呃,这是一个讨厌的陷阱:( –

+2

也可以使用' - >汽车&&'保留至少一些返回类型扣除。 – Predelnik

12

当你function对象返回const A&你提供给它的拉姆达没有。它的返回类型是从return语句中推导出来的,推断为A。尝试添加一个像这样的显式返回类型。

function<const A&(const A& r)> foo1 = [](const A& r) -> const A& { 
    return r; 
};