通过身份函数后,左值引用变为无效

Can*_*hiu 32 c++ c++11

有人解释为什么在通过"身份"功能后引用变得无效,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;
}
Run Code Online (Sandbox Code Playgroud)

问题行与以下方面有何不同:

const A& r = vec[0];
const A& r1 = r;
Run Code Online (Sandbox Code Playgroud)

Bar*_*rry 43

问题是你的lambda.它没有做你认为它做的事情:

function<const A&(const A& r)> foo1 = [](const A& r) { 
//                                               ~~~~~~
    return r;
};
Run Code Online (Sandbox Code Playgroud)

请注意,没有尾随返回类型.这意味着它会自动推断出来.扣除永远不会给你一个引用类型,所以这个lambda返回一个A,而不是一个A const&.这暂时返回A,然后绑定到返回A const&functionoperator().这暂时不是终生延长的.但是,当我们完成通话时foo1(),我们有一个悬挂的参考暂时A.这是未定义的行为,我猜你的编译器会给你一个有用的运行时错误.

要解决此问题,您需要显式指定返回类型:

function<const A&(const A& r)> foo1 = [](const A& r) -> A const& { 
    return r;
};
Run Code Online (Sandbox Code Playgroud)

但即使这样也很危险,因为你仍然可以将一个临时 A函数传递给这个函数并获得一个悬空引用.没有真正的方法围绕那一个.


落入此陷阱的容易程度也是LWG Issue 2813

  • 呃,这是一个令人讨厌的陷阱:( (4认同)
  • 使用` - > auto &&`来保留至少一些返回类型扣除也很有用. (2认同)

Fra*_*eux 12

当你的function对象返回const A&你提供的lambda时,它没有.它的返回类型是从return语句推导出来的,它被推断为A.尝试添加这样的显式返回类型.

function<const A&(const A& r)> foo1 = [](const A& r) -> const A& { 
    return r;
};
Run Code Online (Sandbox Code Playgroud)