C++11/14 中的“xvalue”行为

`xvalue` behavior in C++11/14

class Myclass
{    
public:
    Myclass() = default;
    ~Myclass() = default;
    Myclass(Myclass&&) = default;
    Myclass& operator=(Myclass&&) = default;

    Myclass(const Myclass&) = delete;

    Myclass& operator=(const Myclass&) = delete;
    int i = 0;
};

Myclass GetObj()
{
    Myclass obj;    
    return obj;
}

Myclass WrapperOfGetObj()
{
    Myclass&& Wrapobj = GetObj();
    Wrapobj.i = 1; // Will it work?

    return std::move(Wrapobj);
}

int main()
{
    return 0;
}

我有几个问题: 1)在WrapperOfGetObj函数中,Wrapobjxvalue,所以我可以给它的任何成员赋值(xvalue - 即将过期!!)
2)xvalue的存储是什么?这不是自动存储吗?
3) 当 xvalue 变成 glvalue 并且当它变成 rvalue 时。(以上上下文中的任何例子都会让我明白这一点)。

这些答案将有助于...

Do rvalue references allow dangling references?

What are rvalues, lvalues, xvalues, glvalues, and prvalues?

Real life examples of xvalues, glvalues, and prvalues?

Myclass WrapperOfGetObj()
{
    Myclass&& Wrapobj = GetObj();
    Wrapobj.i = 1; // Will it work?

    return std::move(Wrapobj);
}

1) In WrapperOfGetObj function, Wrapobj is xalue so can i assign value to any member of it (xvalue - going to expire!!)

Wrapobj 是对由 GetObj() 编辑的纯右值 return 的右值引用。该纯右值的生命周期延长至右值引用 Wrapobj 的生命周期,因此访问 .i = 1 没问题。

2) What is the storage of xvalue? is this not automatic storage?

Wrapobj的引用对象有自动存储,会在WrapperOfGetObj结束时析构。

3) When xvalue becomes glvalue and when it becomes rvalue.(Any example in above context will make this clear to me).

xvalue 总是 glvalues。 glvalues 只是所有 'xvalues' 和所有 'lvalues' 的并集,意味着 "has identity." xvalues 也总是右值,它只是所有 "xvalues" 和所有 [=44= 的并集], 表示 "can be moved".

因此,在上面的示例中,Wrapobj 是一个左值(因为它具有标识)、一个右值(因为它可以移动)和一个 x 值(因为它既可移动又具有标识) .

当您从 WrapperOfGetObj() return std::move(Wrapobj) 时,您正在从 std::move 编辑的 xvalue return 构造一个新的纯右值。

表达式Wrapobj是一个左值。所有命名变量都是左值。

我认为您混淆了变量的声明类型与由变量名称组成的表达式的类型和值类别。

decltype(Wrapobj) 给出 MyClass&&。当有人说“Wrapobj 是右值引用”时,他们指的是声明的类型。但是当表达式中使用 Wrapobj 时,它具有类型 MyClass 和值类别 lvalue

不存在引用类型的表达式。此外,表达式的类型和值类别与表达式是否表示临时对象没有直接关系。

对于你的问题2:"xvalue"是表达式的值类。表达式没有存储空间。对象有存储空间。引用可能会也可能不会使用存储空间(未指定)。一定要区分引用的存储和它引用的对象的存储。

GetObj() 的 return 值是一个 临时对象 。该标准实际上并未指定临时对象的存储持续时间,尽管常见的实现使用堆栈(类似于自动对象)。我认为 C++17 可能正在改进标准在这方面的措辞。