Reputation: 785
Consider the following code:
#include <iostream>
#define P_(x) std::cout << x << std::endl
class B {
public:
B() { P_("B::B()"); }
B(const B&) { P_("B::B(const B&)"); }
B(B&&) { P_("B::B(B&&)"); }
~B() { P_("B::~B()"); }
B& operator=(const B&) { P_("B::op=(const B&)"); return *this; }
B& operator=(B&& b) { P_("B::op=(B&&)"); return *this; }
};
class Foo {
public:
void setB(const B& b) { mB = b; }
private:
B mB;
};
B genB() {
return B();
}
int main() {
Foo f;
f.setB(genB());
}
Suppose B
is a type that is difficult to copy-construct. I'd like to generate some B
(with the function genB
) and store it in a Foo
. Since genB
returns a temporary result, I'd expect that a move constructor would be used.
However, when I run the code, I get this output:
B::B()
B::B()
B::op=(const B&)
B::~B()
B::~B()
This clearly shows that two B's get created and destroyed, but that the second is a copy, and not a move of the first.
What is the best way to get move constructors used whenever possible?
B&
and a B&&
?Upvotes: 0
Views: 101
Reputation: 72271
You could overload that setB
function:
class Foo {
public:
void setB(const B& b) { mB = b; }
void setB(B&& b) { mB = std::move(b); }
private:
B mB;
};
Or, you can use the "pass by value" way:
class Foo {
public:
void setB(B b) { mB = std::move(b); }
private:
B mB;
};
Here, the parameter b
will be move constructed when possible or copy constructed otherwise.
Upvotes: 3
Reputation: 16243
The first B
instance is the one created when creating your Foo
instance :
Foo f;
This is because your Foo
class has a B
member called mB
.
The second B
instance is the one created by the genB()
call.
The assignment operator is called because of the assignment you perform in the Foo::setB
function :
mB = b;
Nowhere is there a chance to use a copy or move constructor.
Upvotes: 0