Does std::move leave stack fragmented or is the stack rearranged after moving an object to the caller?

298 Views Asked by At

I have read several answers and and many articles about move semantic so it is simply a static cast to rvalue reference, this question is about its influence on the stack, so is the stack left fragmanted after move? or is it rearranged somehow? as the stack moved objects are not subject to stack unwinding. The following snippet runs fine:

#include <memory>
#include <cassert>

struct A {
    int x = 0;
};

struct B {
    A a;
};

void SetB(B& b) {
    A a1{6}; //pushing into the stack.
    A a2{7}; //pushing into the stack.
    b.a = std::move(a2);
}

int main()
{
    B b;
    SetB(b);
    assert( b.a.x == 7);
}

a2 is defined in SetB stack frame but still available after SetB is finished and the contorl back to main. However; a1 is not despite it is closer to main stack frame?

2

There are 2 best solutions below

3
lorro On

There's no 'stack' in the C++ standard, it's an implementation detail. So a 'generic' answer is difficult as an implementation can have any kind of effect on the given architecture's stack.

That said, the std::move() does not remove the argument from the stack, it remains in a valid-but-undefined state. For your own classes, you might even implement it. Therefore, it's not possible to 'remove' the variable from anywhere - unless, of course, in the optimization phase of the compiler, if it's not accessed anymore.

a2 is not available after SetB is finished. The value is moved to b.a, therefore, b.a is expected to contain the value that a2 has contained before, but it's not the same variable (nor the same memory address).

0
muaz On

With this answer I want to wrap up all infos I got, which really answer my question:

  • For all variables allocated in the stack default move does normal copy (very expensive in case those variables are big) this is something I tested after answers from JaMit, user17732522 and lorro. Originally the question was because I though the compiler will add some measures to manage the stack without copying everything, but it looks I have over-estimated move (no stack fragmentation nor rearrangement, only copy). So in the example above if A is defined like:
struct A {
    int x[1000] = {};
};

moving A results in copying the whole array as is.

  • moving heap resources all depends on the programmer, where move will cast into rvalue reference and once assigned or called inside ctor it will call move assignment or move constructor, and if those are the default ones, it makes shallow copy of pointers which might lead to Segmentation Fault due to dangling pointers.