user1832484
user1832484

Reputation: 371

Moving ctor not kicking-in

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

Answers (1)

Aykhan Hagverdili
Aykhan Hagverdili

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

Related Questions