Home > front end >  Does move constructor change the memory to which "this" points to?
Does move constructor change the memory to which "this" points to?

Time:04-10

I have some confusions about C move constructor. If the compiler is implicitly synthesizing a move constructor, what will this move constructor do? Will it just make "this" point to the object that is used for initialization? there's an example:

struct Foo {
    int i;
    int *ptr;
};

Foo x;
Foo y(std::move(x));

will the implicitly synthesized move constructor just make this in y point to the memory that x is in? If so, how to ensure that x is destructible after the move (if x is destroyed, will members in y be valid)? if not, how does the move constructor of y work?

CodePudding user response:

will the implicitly synthesized move constructor just make this in y point to the memory that x is in?

The synthesized move ctor will memberwise-move the data members of its arguments(x here) to the object being created(y here).

Also, note that for built-in types like int, move is the same as copying.


how to ensure that x is destructible after the move

Since move is the same as copying for built in types, x and y are independent of each other. So when x is destroyed y will not be affected.


will the synthesized move constructor set the ptr of x to nullptr?

No, the synthesize move ctor will not do that for you. It will just memberwise move the data members. For built in types this means the same as copying.


if it does not do this, then the ptr of x will still point to the memory to which the ptr of y points, then you cannot safely destroy x.

In that case, you'd need to write a user-defined move ctor which explicitly sets the ptr of x to nullptr so that when x is destroyed, the y is not affected.

CodePudding user response:

will the implicitly synthesized move constructor just make this in y point to the memory that x is in?

As Anoop noted, it will memberwise call the move constructor on every member of the source to be moved (x) onto the members of the destination (y or this if you imagine yourself "inside" that synthesized move constructor).

So in your example:

  • the int x.i will be moved onto y.i (this->i)
  • the int* x.ptr will be moved onto y.ptr (this->ptr).

Note that these particular moves will be performed by copying.

how to ensure that x is destructible after the move (if x is destroyed, will members in y be valid)?

It's always destructible. As to if it's "valid", it depends. The default move construction was actually a copy. Two objects now point at whatever x.ptr pointed to. If that int was a resource "owned" by x (maybe the resource was a 0 terminated string of ints on the heap), then you've just "shared" that resource.

If you don't wish to "share" it then you could have explicitly written a move constructor for Foo that resets the pointer of the "moved-from" object, or somehow marks it invalid.

struct Foo {
  ...
  Foo(Foo&& other) {
    this->i = other.i;
    this->ptr = other.ptr;
    other.ptr = nullptr;
  }
}

In general, it's best not to rely on "moved from" objects at all, i.e. make sure they are destroyed as soon as possible.

  • Related