Move constructor implementation
On the line commented out ***, why is the Bar copy constructor called? input_bar
is an rvalue reference, so I expect you to call the move constructor. Did it convert to an lvalue reference? I can make a call to the move constructor if I change this line to bar_(std::move(input_bar))
.
#include <iostream>
#include <array>
#include <memory>
class Bar
{
public:
Bar(const Bar& bar)
{
std::cout << "copy constructor called" << std::endl;
}
Bar(Bar&& bar)
{
std::cout << "move constructor called" << std::endl;
}
};
class Foo
{
public:
Foo(Bar&& input_bar) :
bar_(input_bar) // ***
{
}
Bar bar_;
};
int main()
{
Bar bar;
Foo foo(std::move(bar));
return 0;
}
source to share
Once an object has a name, it is explicitly lvalue! If you have a name for an rvalue reference, the entity named is not an r, but an lvalue. The point is that you know that this object is being referenced by an rvalue, and you can legally move its contents.
If you just want to redirect the rvalueness to the next function you call, you should use std::move()
for example:
Foo(Bar&& bar): bar_(std::move(bar)) {}
Without std::move()
, r is considered to be owned by the constructor. With help, std::move()
he releases the ownership and transfers it to the next function.
source to share
You need to move rhrs:
Foo(Bar&& input_bar) :
bar_(std::move(input_bar)) // ***
{
}
We believe that when we do use RHR it should be semantically considered out of scope. Enforcement std::move
allows the following undefined code to be used:
Foo(Bar&& input_bar) {
std::cout << input_bar.baz << std::endl;//not undefined
bar_ = Bar{std::move(input_bar)};//input_bar is now essentailly destroyted
//std::cout << input_bar.baz << std::endl;//Undefined behavior, don't do this
}
The general rule of thumb is that only things without names can actually be used as RHR ... RHR, since the arguments are named and thus will be treated as LHR until you name a function on them.
source to share