2
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;
}

I have few questions: 1) In WrapperOfGetObj function, Wrapobj is xvalue, so can I assign value to any member of it (xvalue - going to expire!!)
2) What is the storage of xvalue? Is this not automatic storage?
3) When xvalue becomes glvalue and when it becomes rvalue.(Any example in above context will make this clear to me).

Ajay
  • 18,086
  • 12
  • 59
  • 105
gaurav bharadwaj
  • 1,669
  • 1
  • 12
  • 29
  • WrapObj is xvalue ? no because value categories {l|r|x} values describe expressions not objects. check link http://stackoverflow.com/questions/9670954/are-temporary-objects-xvalues – PapaDiHatti Nov 07 '16 at 05:45

2 Answers2

3

The expression Wrapobj is an lvalue. All named variables are lvalues.

I think you are mixed up between the declared type of a variable, versus the type and value category of an expression consisting of the variable's name.

decltype(Wrapobj) gives MyClass&&. When someone says "Wrapobj is an rvalue reference", they are talking about the declared type. But when Wrapobj is used in an expression, it has type MyClass and value category lvalue.

There is no such thing as an expression with reference type. Also the type and value category of an expression is not directly related to whether the expression denotes a temporary object or not.

For your question 2: "xvalue" is a value category of expressions. Expressions don't have storage. Objects have storage. References may or may not use storage (it is unspecified). Be sure to distinguish between storage of a reference, and storage of the object it refers to.

The return value of GetObj() is a temporary object. The standard doesn't actually specify a storage duration for temporary objects, although common implementations use the stack (similar to automatic objects). I think C++17 may be improving the standard's wording in this area.

M.M
  • 138,810
  • 21
  • 208
  • 365
  • So according to u Myclass WrapperOfGetObj() { Myclass&& Wrapobj = GetObj(); Wrapobj.i = 1; // Will it work? return std::move(Wrapobj); } Wrapobj.i = 1; may be invalid?? – gaurav bharadwaj Nov 07 '16 at 08:45
  • @gauravbharadwaj your sample code is fine, it is OK to modify temporary objects (as long as they aren't const) – M.M Nov 07 '16 at 09:08
  • So @M.M I am just confused between GetObj() and WrapperOfGetObj() both are returning `lvalue`, first calls `move constructor` and later call `copy constructor`. – gaurav bharadwaj Nov 07 '16 at 09:15
  • @gauravbharadwaj both return by value (not "lvalue") Your question doesn't say anything about when constructors are called ; if you are not sure about that it would be better to post a new question with your code sample (and the output that convinces you what constructors are called) – M.M Nov 07 '16 at 09:24
  • So what's the difference between const Myclass&& Wrapobj = Myclass(); and const Myclass& Wrapobj = GetObj(); ? Thanks! – qianfg Aug 29 '17 at 07:18
  • @qianfg those are exactly identical, other than the result of `decltype(Wrapobj)` (which is something you normally wouldn't do). There is almost never any reason to use const rvalue references in C++ – M.M Aug 29 '17 at 10:45
-1

These answers will help ...

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 is an rvalue reference to the prvalue returned by GetObj(). That prvalue had its lifetime extended to the lifetime of the rvalue reference Wrapobj, so accessing .i = 1 is fine.

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

Wrapobj's referenced object has automatic storage and will destruct when WrapperOfGetObj finishes.

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

xvalue's are always glvalues. glvalues are just the union of all 'xvalues' and all 'lvalues' and means "has identity." xvalues are also always rvalues, which is just the union of all "xvalues" and all "prvalues", and means "can be moved".

So, in the example above, Wrapobj is a glvalue (since it has identity), an rvalue (since it can be moved), and an xvalue (since it is both moveable and has identity).

When you return std::move(Wrapobj) from WrapperOfGetObj() you are constructing a new prvalue from the xvalue returned by std::move.

Community
  • 1
  • 1
pat
  • 763
  • 4
  • 12
  • The expression `Wrapobj` is an lvalue, and not an rvalue nor an xvalue. The three categories "lvalue, xvalue, prvalue" do not overlap, any expression is exactly one of the three. Also you mix up expressions with objects, e.g. "constructing a new prvalue" should be "constructing a new temporary". "prvalue" refers to expressions, not objects. – M.M Nov 07 '16 at 06:02
  • As @m-m said, please see your answer again. – gaurav bharadwaj Nov 07 '16 at 08:46