14

我试图理解 C++11 中的左值和右值。于是我写了一段测试代码:

int x = 10;
int foo() { return x; }
int& bar() { return x; }
int&& baz() { return 10; }

int main() {
    int& lr1 = 10;     // error: lvalue references rvalue
    int& lr2 = x;      // ok
    int& lr3 = foo();  // error: lvalue references rvalue
    int& lr4 = bar();  // ok
    int& lr5 = baz();  // error: lvalue references rvalue

    int&& rr1 = 10;    // ok
    int&& rr2 = x;     // error: rvalue references lvalue
    int&& rr3 = foo(); // ok
    int&& rr4 = bar(); // error: rvalue references lvalue
    int&& rr5 = baz(); // ok
}

它工作得很好,所以我插入了 std::cout 来打印结果。

#include <iostream>

int x= 10;
int foo() { return x; }
int& bar() { return x; }
int&& baz() { return 10; }

int main() {
    int& lr1 = 10;     std::cout << lr1 << std::endl; // error
    int& lr2 = x;      std::cout << lr2 << std::endl; // ok
    int& lr3 = foo();  std::cout << lr3 << std::endl; // error
    int& lr4 = bar();  std::cout << lr4 << std::endl; // ok
    int& lr5 = baz();  std::cout << lr5 << std::endl; // error

    int&& rr1 = 10;    std::cout << rr1 << std::endl; // ok
    int&& rr2 = x;     std::cout << rr2 << std::endl; // error
    int&& rr3 = foo(); std::cout << rr3 << std::endl; // ok
    int&& rr4 = bar(); std::cout << rr4 << std::endl; // error
    int&& rr5 = baz(); std::cout << rr5 << std::endl; // ERROR!?
}

int&& rr5 = baz(); std::cout << rr5;导致运行时错误,但我不知道为什么会出错。

我认为的返回值baz()将是 xvalue,因此它的生命周期会延长。但是当我试图访问它的值时,就会发生错误。为什么?

4

1 回答 1

20

我认为的返回值baz()将是 xvalue,因此它的生命周期会延长。

起初baz()返回的总是一个悬空引用。

对于int&& baz() { return 10; }临时的生命周期没有延长。它是在函数内部构造的,在离开函数时会被销毁,然后baz()总是返回一个悬空引用。

临时绑定到return语句中函数的返回值不会被扩展:它在返回表达式的末尾立即被销毁。这样的函数总是返回一个悬空引用。

那么 for int&& rr5 = baz();,rr5也是一个悬空引用;对它的尊重导致UB,一切皆有可能。

另一方面,如果您更改baz()为按值返回,一切都会好起来的;返回值被复制然后绑定到rr5,然后临时的生命周期延长到 的生命周期rr5

居住

于 2017-07-11T09:54:44.660 回答