matrixisreal
matrixisreal

Reputation: 218

C++ - Does the Destructor just deallocate the memory or does it actually delete the object?

To check this, I have run this small test code.

#include <iostream>
using namespace std;

class name {
public:
  int data;
  name(int data) {
    this->data = data;
  }
  void printData() {
    cout << data << endl;
  }
};

int main() {
  name* namePointer;
  {
    name n(5);
    namePointer = &n;
  }
  namePointer->printData();
}

So, two questions:

  1. The name object n is created in the block inside main and its pointer is saved, to make sure its destructor is called when we get out of the block. But the pointer points to the same object and its member functions are still accessible. Doesn't this mean that the object isn't deleted yet?

  2. Say I add this to my name class:

    ~name() {
        cout << "destructor called" << endl;
    }
    

    Does overriding the destructor function, and doing nothing in it (here in ~name()), prevent the object from being deleted?

Edit: Thanks for the responses, it really helped. But May I know the reason for these down votes, I think this is a really good question. ¯_(ツ)_/¯

Upvotes: 4

Views: 4805

Answers (4)

2785528
2785528

Reputation: 5566

1 ... Doesn't this mean that the object isn't deleted yet?

No.

2 ... Does overriding the destructor function, and doing nothing in it (here > in ~name()), prevent the object from being deleted?

No.

cout's are your friends.

Here is my version of your code (I have applied my coding standards for names)

#include <iostream>

class Name_t
{
   int m_data;
public:
   Name_t(int data) : m_data(data) {
      std::cout << "\n  Name_t::ctor" << std::endl;
   }
   ~Name_t() {
      std::cout << "\n  Name_t::dtor" << std::endl;
   }

   void cout() { std::cout << "\n  Name_t.cout() "
                           << m_data << std::endl; }
};

class T517_t
{
public:
   T517_t() = default;
   ~T517_t() = default;

   int exec()
      {
         Name_t* Name_tPointer = nullptr;
         {
            Name_t n(5);
            Name_tPointer = &n;
         }
         Name_tPointer->cout();
         return(0);
      }    
}; // class T517_t

int main(int , char** )
{
   int retVal = -1;
   {
      T517_t   t517;
      retVal = t517.exec();
   }
   return(retVal);
}

Running this, you see both ctor and dtor run before the UB (undefined behavior).

  Name_t::ctor

  Name_t::dtor

  Name_t.cout() 5

Another indicator (via cout) is to clear or invalidate the data in the dtor ... I seldom do this except during diagnostics.

Replace dtor with

   ~Name_t() {
      m_data = -1;
      std::cout << "\n  Name_t::dtor" << std::endl;
   }

One can see that the dtor has invalidated your data.

  Name_t::ctor

  Name_t::dtor

  Name_t.cout() -1

Does destructor deallocate memory?

Which memory?

No - The dtor of the object does not deallocate the object.

Yes - The dtor of the object should deallocate any memory allocated in the ctor (Ying and Yang) unless already deleted by some other method of the instance.

Upvotes: 1

eerorika
eerorika

Reputation: 238311

Does the Destructor just deallocates the memory or actually deletes the object

A destructor calls the destructors of subobjects (if any), executes the destructor body (if it is defined). It is technically not the destructor that deallocates the memory. The destrcutor can be called without deallocation, and memory can be deallocated without the call to a destructor.

When a dynamic object is deleted with operator delete, the destructor will be called, and then the memory is deallocated. Likewise, when the life time of an automatic variable (such as your n) ends, its destructor is called, and the memory is deallocated.

It is unclear what you mean by "deletes the object". A destructor will never call the delete operator (unless the body of the destructor {,of a sub object} sub object calls delete operator, but then it is not this that is deleted).

If you mean whether destructor destroys the object, then it is the other way 'round: When an object is being destroyed, its destructor will be called.

  1. ... But the pointer points to the same object

The pointer points to where the object was. That object has been destroyed and no longer exists.

... and its member functions are still accessible.

Accessibility of a member function does not depend on what is being pointed. Dereferencing a pointer (including calling a member function) that does not point to an object has undefined behaviour.

Doesn't this mean that the object isn't deleted yet?

No. You can't make conclusions from undefined behaviour.

  1. Does overriding the destructor function ...

This is not overriding. Overriding is a specific language term that involves inheritance and virtual functions.

What you have done is define a destructor.

  1. ... and doing nothing in it (here in ~name()), prevent the object from being deleted?

No. Doing nothing in the body of the destructor is exactly the same what the implicit destructor does (the one that the object had when you left the destructor undefined). It does not "prevent the object form being deleted".

Upvotes: 5

SergeyA
SergeyA

Reputation: 62553

In C++ parlance, two separate concepts are 'object lifetime' and 'storage duration'. A duration is pretty much the same as lifetime, but Standard uses two distinct words here. Storage refers to the physical memory occupied by the object, while object lifetime refers to the time when it is allowed to access the object.

With this in mind, one has two understand that constructor and destructor determine object lifetime - it is not allowed to access the object before constructor was called and after destructor was called, and do not say anything about storage lifetime. It is obvious that storage duration (or lifetime) should not be smaller than object lifetime - once can not access object that has no physical representation - but can be longer than it.

It is easily seen when placement new is used together with explicit destructor call - storage remains available, but the object has gone.

Upvotes: 4

Cory Kramer
Cory Kramer

Reputation: 117856

It is undefined behavior to use namePointer after that block because it is a dangling pointer. How it behaves after that (correctly or incorrectly) can change on different machines, compilers, etc.

Overriding the destructor to output some text won't change the fact that the object's memory is still deallocated. So in this case the destructor of n will be called at the end of the block, which will delete the object and its member variables.

Upvotes: 1

Related Questions