0
#include <iostream>
#include <string>

using namespace std;

string&& f(string&& rvf)
{
    cout << rvf << endl;

    return (string&&)rvf;
    // in the return statement, how rvf has become an lvalue?
    // because of this I had to typecast explicitly
}

string&& g()
{
    return "xyz";
}

int main()
{
    string&& st = f("rvalue");

    cout << "f " << st << endl;

    string&& st2 = g();

    cout << "g " << str2 << endl;
    // why  this line prints junk / crashes some times?

    return 0;
}

general questions:

when we assign rvalue to a normal variable, how the copying is done? How exactly the rvalue value is "moved" into another variable?

and what happens to rvalue after copying? will it be destroyed immediately or when its out of scope?

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
chai512
  • 171
  • 2
  • 13

1 Answers1

2
// in the return statement, how rvf has become an lvalue?

Although the type of rvf is an rvalue reference to std::string, rvf itself is an lvalue. Think about it this way: rvf is a named variable which you can take the address of; you can be pretty sure that's an lvalue.

// why  this line prints junk / crashes some times?

Because you have undefined behaviour in g:

string&& g()
{
    return "xyz";
}

That constructs a temporary std::string, then returns a reference to it. Regardless of whether that's an lvalue or rvalue reference, you're going to be down the hole of undefined behaviour as soon as you read it.

when we assign rvalue to a normal variable, how the copying is done? How exactly the rvalue value is "moved" into another variable?

This depends on the class. For built-in types, a move is the same as a copy. Think about how you would "move" an int; it doesn't really make sense. For classes like std::vector, it essentially copies over the pointer to the internal dynamically-allocated buffer, then sets it to nullptr in the original (that's one possible implementation anyway).

and what happens to rvalue after copying? will it be destroyed immediately or when its out of scope?

Again, that depends on the class. Standard library classes are in a "valid, but unspecified state" after being moved from, so they still satisfy any class invariants, but you shouldn't rely on anything useful being there. You could happily write a standards-conforming class which you can't access after being moved from without hitting undefined behaviour.

TartanLlama
  • 63,752
  • 13
  • 157
  • 193