【问题标题】:Some differences between xvalue and prvaluexvalue 和 prvalue 之间的一些区别
【发布时间】:2021-01-31 03:55:32
【问题描述】:

我最近一直在仔细研究 C++ 类别。 lvalue 和 rvalue 之间的区别似乎很清楚,但是当谈到 prvalue 和 xvalue 时,我感到困惑。
举个例子:

#include <iostream>
using std::cout;
using std::endl;
using std::move;
class Type {
public:
    int value;
    Type(const int &value=0) :value(value) {}
    Type(const Type &type) :value(type.value){}
    Type(Type &&type) noexcept :value(type.value) {}
    Type &operator= (const Type &type) {
        value = type.value;
        return *this;
    }
    Type &operator=(Type &&type) noexcept{
        value = type.value;
        return *this;
    }
};
Type foo1(const Type &value) {
    return Type(value);
}
Type &&foo2(const Type &value) {
    return Type(value);
}
int main() {
    Type bar1(123);
    cout << foo1(bar1).value << endl;
    cout << foo2(bar1).value << endl;
    Type bar2;
    bar2 = foo1(bar1);
    cout << bar2.value << endl;
    bar2 = foo2(bar1);
    cout << bar2.value << endl;
    return 0;
}

运行示例,控制台输入:
123
123
123
-858993460
谁能解释为什么它在最后一个输出中给出了一个意外的值?
这个例子展示了 xvalue 的什么特点?

【问题讨论】:

  • foo2 返回对已销毁的局部变量的引用。所以参考是悬空的。这与prvalues vs xvalues 没有任何关系。

标签: c++ c++11 lifetime xvalue prvalue


【解决方案1】:

foo2 正在返回绑定到临时的引用,该引用立即被销毁;它总是返回一个悬空的reference

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

foo2(bar1).valuebar2 = foo2(bar1); 这样的返回引用的取消引用导致UB;一切皆有可能。

另一方面,foo1 没有这样的问题。返回值从临时对象中移出。

【讨论】:

  • 你的意思是即使 foo2(bar1).value 给出了正确的结果,这只是未定义行为的巧合?
  • @true_mogician 是的,行为无法保证。
  • @true_mogician BTW gccfoo2(bar1).value 上给出分段错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-03-07
  • 1970-01-01
  • 1970-01-01
  • 2012-12-09
  • 2017-09-12
  • 2015-04-10
相关资源
最近更新 更多