Reputation: 371
following code
#include <iostream>
class C
{
public:
C(int i) : i{i}{ }
C(const C&) = delete; // no copy allowed
C(C&& c){ std::cout << "moving from " << c.i << '\n'; i = c.i--; }
int i;
};
void func(C&& c) { std::cout << "func c " << c.i << '\n'; }
int main()
{
C c{123};
func(std::move(c));
std::cout << "c " << c.i;
}
outputs
func c 123
c 123
so moving ctor is not kicking-in: why?
Additional question: given
void func(C&& c1, C&& c2) { ... }
is legal calling it twice using same argument?
func(std::move(c), std::move(c));
I would say no, since, independently from which argument is evaluated first, it should not be legal to move when evaluating the other one. But:
void func(C&& c1, C&& c2) { std::cout << "func c1 " << c1.i << " c2 " << c2.i << '\n'; }
int main()
{
C c{123};
func(std::move(c), std::move(c));
std::cout << "c " << c.i;
}
outputs
func c1 123 c2 123
c 123
so moving ctor is not kicking-in again.
Upvotes: 0
Views: 85
Reputation: 29985
std::move
doesn't actually call the move constructor. It is a cast to r-value reference (akin to static_cast<C&&>(c)
). Once this is done, if you try to copy that object, it will call the move-constructor or the move-assignment operator. If you don't try to copy that object, nothing happens. Try this:
// By value
void func(C c) { std::cout << "func c " << c.i << '\n'; }
// By r-value reference
void func2(C&& c)
{
C c1{std::move(c)};
std::cout << "func2 c " << c.i << '\n';
}
int main()
{
C c{123};
func(std::move(c));
func2(std::move(c));
std::cout << "c " << c.i;
}
Upvotes: 3