0

I have copy constructors and move constructors defined in class Foo. In debugging I step in f = CreateFoo(1, 1); and it takes me to Foo(Foo&& other) : Foo(other, 0) {}. The next step-in takes me to Foo(Foo& other, int m) :x(other.x + m), y(other.y - m) {} which is a copy constructor. I am delegating a move constructor, I am expecting it executes Foo(Foo&& other, int m) : x(std::move(other.x)), y(std::move(other.y)). I don't understand why? Can anyone give me some help? Below is the full program.

class Foo
{
public:
    int x;
    int y;
public:
    Foo(int i, int j) : x(i), y(j) {}
    Foo(Foo& other) : x(other.x), y(other.y) {}
    Foo(Foo& other, int m) :x(other.x + m), y(other.y - m) {}
    Foo(Foo&& other, int m) : x(std::move(other.x)), y(std::move(other.y))
    {
        x = x + m;
        y = y - m;
    }
    Foo(Foo&& other) : Foo(other, 0) {}
    Foo& operator=(const Foo& other) {
        x = other.x;
        y = other.y;
        return *this;
    }

    Foo& operator=(Foo&& other)
    {
        x = std::move(other.x);
        y = std::move(other.y);
        return *this;
    }
};

Foo CreateFoo(int x, int y)
{
    Foo tmp(x, y);
    return tmp;
}

int main()
{
    Foo f(0, 0);
    f = CreateFoo(1, 1);
    system("pause");
    return 0;
}
songyuanyao
  • 169,198
  • 16
  • 310
  • 405
inflator
  • 39
  • 4
  • You have to delegate using `std::move(other)`. – ph3rin Oct 12 '19 at 00:24
  • Possible duplicate of [Move constructor on derived object](https://stackoverflow.com/questions/4086800/move-constructor-on-derived-object) – walnut Oct 12 '19 at 00:27
  • Inside of `Foo(Foo&& other)`, `other` is an lvalue since it has a name, which is why `Foo(Foo& other, int m)` gets delegated to. Use `std::move(other)` to make an rvalue reference so it can delegate to `Foo(Foo&& other, int m)` instead: `Foo(Foo&& other) : Foo(std::move(other), 0) {}` – Remy Lebeau Oct 12 '19 at 00:28
  • Duplicate talks about base constructor, but same applies here. – walnut Oct 12 '19 at 00:28
  • Btw. a copy constructor should take its argument by `const` reference. – walnut Oct 12 '19 at 00:29
  • A move of an int will just copy. The move is used for container objects to transfer ownership, leaving the moved-from container object in a valid-but-unspecified state (good for assigning-to or destructing, and any methods that have no preconditions.... but best just to let the moved-from object destruct and not use it anymore). – Eljay Oct 12 '19 at 00:32

1 Answers1

2
Foo(Foo&& other) : Foo(other, 0) {}

Here other is a lvalue (it has a name!). You need to delegate the call by using std::move again, to make it an xvalue:

Foo(Foo&& other) : Foo(std::move(other), 0) {}
ph3rin
  • 4,426
  • 1
  • 18
  • 42