user8182402
user8182402

Reputation:

Confusion between rvalue references and const lvalue references as parameter

So the parameter list for a copy constructor consists of an const lvalue reference, like const B& x. The parameter list for a move constructor, however, consists of an rvalue reference, like B&& x.

When I discovered this, it seemed odd to me, so I tried to define a function taking a const lvalue reference as an argument:

void calculator(const Intvec& veccor) 
{ 
cout << "in veccor" << veccor.m_size << "\n"; 
}

I already knew that const lvalue reference can bind to anything, so the result was sort of expected. I tried calling the function with both and lvalue and an rvalue and as expected, it all worked:

calculator(Intvec(33)); //works
Intvec newvec(22);
calculator(newvec); //works

I then tried to change the parameter list of calculator to an rvalue reference, and as expected, only the rvalue worked when calling it.

So since a const lvalue reference can take both lvalues and rvalues as an argument, why does the move constructor not just use a const lvalue reference instead of an rvalue reference? And why not just always use const lvalue references in general, like in cases where you would not do the same as what is happening in a move constructor?

Upvotes: 7

Views: 3466

Answers (1)

eerorika
eerorika

Reputation: 238491

If a move constructor accepted a const lvalue reference, then such declaration of a move constructor would be indistinguishable from a copy constructor. There has to be a way to distinguish them, and the language has been specified such that a move constructor takes an rvalue reference as the argument.

A move constructor that would accept a const lvalue reference would not allow the moved from object to be modified, so you couldn't do anything that you couldn't do in a copy constructor. In fact, such move constructor would be in every way identical to a copy constructor. Why would one call something a move constructor when it is exactly the same as a copy constructor?


PS. Your experiment reveals an interesting fact: As long as a class has a copy constructor (and the move constructor is not explicitly deleted), whether it has a move constructor or not does not affect how that object can be used. In any case where a move is appropriate, a copy can be used instead if the class has no move constructor.

Upvotes: 6

Related Questions