c++c++14xvaluevalue-categoriesprvalue

Behavioral differences in 5 vs std::move(5)


I've read all the major questions on SO about different value categories but still don't clearly understand the difference between, in this case, xvalues vs prvalues.

I know that, like all glvalues, xvalues can have their dynamic type different from the static one, but e.g. in case of literal vs std::move from literal I can't find 'real' behavioral differences (maybe apart from those that are formally based on what's xvalue and what's prvalue, like which constructor will get called in MyClass(std::move(5)); but it doesn't seem that important in case of literals since their values won't be used anyway.

What is the actual 'benefit' I can get from calling std::move on a literal?


Solution

  • What is the actual 'benefit' I can get from calling std::move on a literal?

    None. A (non-string) literal is a prvalue, which is an rvalue. Calling std::move() will give you an xvalue, but that is still an rvalue. There's no way to overload on the difference between xvalue and prvalue - you can only overload on the difference between lvalue and rvalue - so there's no subsequent difference.

    However, if we generalize to calling std::move on a prvalue, there is one big anti-benefit: you lose temporary lifetime extension in some places where you might need it. Consider:

    SomeContainer foo();
    for (auto&& elem : foo()) { ... }
    

    That works fine. You can iterate over a prvalue like that. However, this does not work at all:

    SomeContainer foo();
    for (auto&& elem : std::move(foo())) { ... }
    

    We still have an rvalue of type SomeContainer, but now our temporary is bound to the reference parameter of move() so it goes out of scope before the body of the for loop is entered. Oops.