0

After reading some materiales about rvalue reference i have more question then answers. From here i have read about rvalue ref:

Here i made a simple example to help me understand:

#include <iostream>

using namespace std;

class A
{
public:
A() :m_a(0), m_pa(nullptr) { cout << "constructor call" << endl; };
~A() { cout << "destructor call" << endl; };

A(A& other) :m_a(0), m_pa(nullptr)
{
    cout << "copy constructor" << endl;
}

A(A&& other) :m_a(0), m_pa(nullptr)
{
    cout << "move constructor" << endl;
}

A& operator=(A&& other)
{
    this->m_a = other.m_a;
    this->m_pa = other.m_pa;
    other.m_a = 0;
    other.m_pa = nullptr;
    return *this;
}

A& operator=(A& other)
{
    this->m_a = other.m_a;
    this->m_pa = other.m_pa;
    other.m_a = 0;
    other.m_pa = nullptr;
    return *this;
}

private:
int m_a;
int* m_pa;
};

int main()
{
A(test2);//constructor
A test4(test2);//copy constructor
//? - move constructor
return 0;
}

I don't understand what is so special with &&. In the above example i can do something like this with &.

A& operator=(A& other)
{
    this->m_a = other.m_a;  //copy value
    this->m_pa = other.m_pa;//copy pointer address
    other.m_a = 0;          
    other.m_pa = nullptr;//clean "other" object properties from preventing destructor to delete them and lose pointer address
    return *this;
}

Question:

  • If i can do this with & without using extra memory allocation and copy operation why should i use &&?
  • How is a value value taken that has no identifier and saved?

Example 2:

#include <iostream>

using namespace std;

void printReference (int& value)
{
    cout << "lvalue: value = " << value << endl;
}

void printReference (int&& value)
{
    cout << "rvalue: value = " << value << endl;
}

int getValue ()
{
int temp_ii = 99;
return temp_ii;
}

int main()
{ 
  int ii = 11;
  printReference(ii);
  printReference(getValue());  //  printReference(99);
  return 0;
}

Question:

  • Why to use && in this case and how does this help me? Why not just store the return of getValue and print it?
user1810087
  • 5,146
  • 1
  • 41
  • 76

3 Answers3

0

If i can do this with & without using extra memory allocation and copy operation why should i use &&?

The assignment operators you wrote taking & lvalue references are very, very bad. You don't expect statements like

a = b;

to damage b, but that's what you're suggesting. The usual assignment operator takes a const& precisely because it shouldn't alter the right-hand-side of the expression.

So, you should use the rvalue-reference assignment operator (move assignment) when you do want to steal the right-hand-side's state, such as when it's an anonymous temporary or you explicitly move it:

a = return_anonymous_temporary(); // ok: the rhs value would expire anyway
a = std::move(b);                 // ok: the damage to b is explicit now

That behaviour shouldn't be the default, though.

Useless
  • 64,155
  • 6
  • 88
  • 132
  • How should i use "A" object from the first example in main to call move constructor and not copy?I can't figure it out.. –  Aug 23 '17 at 09:59
  • The move constructor takes an rvalue reference, so you need one of those. That can be an anonymous temporary or the result of `std::move` as I showed in the answer. It behaves exactly the same as the move-assignment operator in this respect. – Useless Aug 23 '17 at 12:12
0

If i can do this with & without using extra memory allocation and copy operation why should i use &&?

Because it allows you to overload a function for rvalues and lvalues and have different behaviour for each. You have same behaviour in both overloads, so you don't need an rvalue reference in this case.

More generally, an rvalue reference argument allows you to pass a temporary, while allowing a move from that argument.

Why to use && in this case and how does this help me?

It allowed you to print "rvalue" when the argument was an rvalue.

Why not just store the return of getValue and print it?

Then you won't be able to print "rvalue" for rvalues and "lvalue" for lvalues.


Except for move constructor/assignment operator, there are not many cases where r-values are useful.

eerorika
  • 232,697
  • 12
  • 197
  • 326
0

After you read some stuff about rvalues, here is some more material about rvalues.
I think the point you are probably missing, is not (only) what you can do but what you should do.

Your first example has several issues:

Your are not able to copy a const value to an instance of A.

const A a1;
A a2(a1);   // won't compile
A a3;
a3 = a1;    // won't compile

I don't understand what is so special with &&. In the above example i can do something like this with &.

Yes you could do what you suggested. But it is purely designed copy assigment. Consider this:
I wrote a shared library where my copy ctor is like you did in your suggestion. You don't have access to my code, just the header. In my copy ctor and assigment operator i take ownership of the instance you passed to my library. There is no description what the assignment is doing... Do you see the point, I must not take ownership of your instances! eg:

// my header:
// copy ctor
A& operator=(A& other); 

// your code:
A a1;
A a2(a1);   // from now on, a1 is broken and you don't know it!!!
cout << a1; // pseudo code: prints garbage, UD, crash!!!

You always should define copy-ctors/assignments parameters const:

A(A const& other);
A& operator=(A const& other);
// ...
const A a1;
A a2(a1);           // will compile
A a3;
a3 = a1;            // will compile + due to the fact a1 is passed const a3 cannot mutate a1 (does not take ownership)
cout << a1;         // pseudo code: everything is fine
a3 = std::move(a1); // a3 takes ownership from a1 but you stated this explicitly as you want it

Here is a small example you can play with. Notice the copy constructor is const but the copy assignment is not. Then you can see how they differ.

user1810087
  • 5,146
  • 1
  • 41
  • 76