c++ - 通过标识函数后,左值引用变得无效

标签 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;
}

问题线有何不同:

const A& r = vec[0];
const A& r1 = r;

最佳答案

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

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

请注意,没有尾随返回类型。这意味着它是自动推断的。推导永远不会给你一个引用类型,所以这个 lambda 返回一个 A,而不是一个 A const&。然后将返回的临时 A 绑定(bind)到 functionoperator() 的返回 A const&。那个临时的不是终生延长的。但是当我们完成调用 foo1() 时,我们有一个对该临时 A 的悬空引用。这是未定义的行为,我猜你的编译器会给你一个有用的运行时错误。

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

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

但即使这样也很危险,因为您仍然可以将 temporary A 传递给此函数并获取悬空引用。没有真正的解决方法。


落入这个陷阱的难易程度也是LWG Issue 2813

关于c++ - 通过标识函数后,左值引用变得无效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42162199/

相关文章:

c++ - 如何在参数包中找到最大值?

c++ - move 语义无意中被封装指针的类中的复制构造函数取代

c++ - 传递 std::type_info 来识别 void *

C++ 编译器警告 - 返回局部变量

c++ - Lua:加载文件后获取全局函数失败

c++ - 当 GUI 线程在 Qt 中空闲时发出信号?

c++ - 使用 C++11/14 正确定义 DLL 接口(interface)

c++ - 在 mac os x 的命令行中将 clang 与 libc++ 和 c++11 结合使用

android - Android NDK 中的 u16string 和 char16_t

c++ - OpenGL/过剩 : Making the camera rotate around X axis with arrow keys?