0

So I recently found this snippet on a c++ course:

class Move
{
private:
    int* data;
public:
    Move(int d) {
        data = new int;
        *data = d;
    }
    Move(const Move& source): Move(*source.data) {
        std::cout << "Copy constructor invoked!" << std::endl;
    }
    Move(Move&& source) noexcept : data(source.data) {
        source.data = nullptr;
    }

    ~Move() {
        delete data;
        std::cout << "Destroyed" << std::endl;
    }
};

int main() {
    std::vector<Move> vec;

    vec.push_back(Move{ 10 });
    vec.push_back(Move{ 20 });

    return 0;
}

Now i'm really stuck with how it precisely works, so first let's say that there is no move constructor and only a copy constructor: On cppreference, they specify that the vector push_back method takes a val and:

The content of val is copied (or moved) to the new element.

  • I don't understand, when is the value copied or moved, does it have to do with the constructors available or nothing like that?
  • Also here the r-value evaluates to a temporary object(Move{10}), why does it have to be copied? Can't it just be pushed?
  • And why is the destructor called twice on the push_back line, shouldn't it be called at the end of the program because how will we access the object in the vector then?

And now let's say there is only the move constructor:

  • So what happens precisely here, from what I understand it see's an r-value so then it invokes the move constructor which create's an object with the data of the r-value object and then nulls out it's pointer, why would he null out the pointer? I don't really understand the purpose of this line source.data = nullptr;
  • And then why again does it invoke the destructor twice on the same line, why would it want to delete the created object, how will a destroyed object go inside a vector?

I know there is some questions here, but I've been trying to figure them out for several hours now and I still can't visualize the process here. Thanks in advance.

Alex
  • 840
  • 7
  • 23
  • If I were you, I'd step through the running program with a debugger. Then I'd make the changes that you ponder about, and see what happens. I'd also add more `std::cout` and also output `static_cast(this)` to help identify the objects in the output. – Eljay Mar 27 '20 at 10:39
  • Moving doesn't prevent construction or destruction of objects, but it allows to efficiently transfer the **contents** of an object. – Timo Mar 27 '20 at 10:39
  • @Timo, it answers alot in my question, but wait, I still don't understand which the moved object is destroyed after the semicolon... – Alex Mar 27 '20 at 10:53
  • 1
    You will always get 1 destruction from your function argument, because that's a different object than the object that lives in the vector. You might get more destructions if the vector has to grow in size because then it has to move the objects that are alredy in the vector to a new (larger) location in memory. This causes some internal moves. – Timo Mar 27 '20 at 10:57
  • @Timo Ohhh ok I see, Thank you! – Alex Mar 27 '20 at 10:59
  • 1
    You null out the pointer so that the "moved from" object will not try to delete the data in it's destructor. In other words, the ownership has been transferred. – super Mar 27 '20 at 11:00
  • @super Ok thank you, one more question why in the first place is the copy constructor called in `vec.push_back(Move{10})`? – Alex Mar 27 '20 at 11:13
  • @Alex It is? I would expect it not to ever call the copy-constructor with this code. What compiler are you using? `std::vector::push_back` has had an r-value overload since `c++11`. – super Mar 27 '20 at 13:32

0 Answers0