c++constructordestructorraiimember-variables

Does destructor take care of popping member variables from the stack


Take this very simple class. The main() function just creates an object of it. Even though the constructor and destructor don't have an implementation here. My assumption is that the constructor will push the three member variables onto the stack when the object is created.

At the end of main() the object's destructor will get implicitly called. Is it the job of the destructor to then pop these variables off the stack?

class MyClass1
{
   public:
       MyClass1(){}
       ~MyClass1(){}

   private:
      int num1_ = 1;
      int num2_ = 2;
      int num3_ = 3;
};

int main()
{
     MyClass1 mc1; // Constructor gets called

     // Destructor implicitly called here as the object is going out of scope
}

Solution

  • No, the destructor does not pop member variables. Likewise, the constructor does not push member variables.

    The job of a constructor is to initialize already-allocated storage so that, afterward, that storage contains a valid object. Symmetrically, the job of a destructor is to perform any necessary cleanup before the object's storage is reclaimed; when the destructor returns, the storage is still allocated, but does not contain a valid object anymore.

    For your main() function, when compiled by a typical compiler, the generated object code will begin by reserving storage for mc1 on the call stack. Normally this is done by adjusting the stack pointer register. We don't usually refer to this as "pushing", because to "push" there should be an existing value being pushed, whereas here, typically, the reserved storage is left uninitialized.

    Then, main() will invoke the constructor, passing the address of the reserved stack storage as the this argument. For this program, the constructor will write the values 1, 2, and 3 into the passed storage.

    Next, main() will invoke the destructor, again passing the same address as the this argument. For this program, the destructor will not do anything.

    Finally, main() will reclaim the storage used by mc1 by adjusting the stack pointer register back to what it was originally. This would not usually be called "popping" because the values contained in the storage are discarded.

    The key point is that allocation (including on the stack) and construction are separate activities, as are deallocation and destruction.

    In fact, it is possible to invoke a constructor on already-allocated storage by using the "placement new" syntax, and possible to explicitly invoke a destructor without reclaiming storage, although in both cases one must be careful not to violate the language rules and thereby cause undefined behavior.