I have a class A
that prints out a message when constructed/copied/moved
class A
{
public:
A(std::string s)
:s_(s)
{
std::cout << "A constructed\n";
}
~A()
{
std::cout << "A destructed\n";
}
A(const A& a)
:s_(a.s_)
{
std::cout << "A copy constructed\n";
}
A(A&& a)
:s_(std::move(a.s_))
{
std::cout << "A moved\n";
}
A& operator=(const A& a)
{
s_ = a.s_;
std::cout << "A copy assigned\n";
}
A& operator=(A&& a)
{
s_ = std::move(a.s_);
std::cout << "A move assigned\n";
}
std::string s_;
};
In main
, I construct an instance of A
, capture that in a lambda by value, copy that lambda into a std::function
, and finally move that std::function
into another std::function
int main()
{
A a("hello ");
std::function<void()> f = [a]{ std::cout << a.s_; };
std::function<void()> g(std::move(f));
}
This prints out the following
A constructed
A copy constructed
A copy constructed
A destructed
A destructed
A destructed
Why is the move constructor of A
not invoked? Shouldn't the last step of moving f
into g
have invoked A
's move constructor?
The copy constructor isn't called precisely because you have moved the std::function
. This is because std::function
can optionally store the captured values on the heap and retain a pointer to them. Thus moving the function simply requires moving that internal pointer. Obviously MSVC opts to store the captures on the heap and GCC etc. opt to store them on the stack thus requiring the captured values to be moved as well.
Edit: Thanks to Mooing Duck for pointing out in a comment on the question that GCC is also storing the captures on the heap. The actual difference seems to be that GCC moves the captures from the lambda to the std::function
when it is constructed from the lambda.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With