4

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. ¯_(ツ)_/¯

matrixisreal
  • 289
  • 4
  • 11
  • Don't conflate "value" with "memory". A destructor call (should) only invalidates the value of the object. – StoryTeller - Unslander Monica Aug 02 '17 at 14:07
  • A destructor *only* destroys and cleans up the object. It does not deallocate the memory. That's managed by a separate mechanism, outside the desctructor. – François Andrieux Aug 02 '17 at 14:07
  • 2
    I recommend reading this: https://isocpp.org/wiki/faq/dtors – Fred Larson Aug 02 '17 at 14:08
  • @matrixisreal you never allocate any memory on the heap, and your referencing a stack variable that goes out of scope, that variable's memory is cleaned up then completely separate from your destructor – Austin_Anderson Aug 02 '17 at 14:14
  • I do not agree with duplicates. They talk about accessing object after it has been deleted, but the question is "Does the Destructor just deallocates the memory or actually deletes the object". Provided duplicates do not answer this question. – SergeyA Aug 02 '17 at 14:24
  • @SergeyA this is exact duplicate of https://stackoverflow.com/questions/6441218/can-a-local-variables-memory-be-accessed-outside-its-scope/6445794#6445794 – Slava Aug 02 '17 at 14:28
  • @Slava, how does the answer in this question answer the question 'does destructor deallocates the memory'? (sorry for alliterations) – SergeyA Aug 02 '17 at 14:30
  • @SergeyA it perfectly answers "Doesn't this mean that the object isn't deleted yet." and explains why OP observes such behavoir. – Slava Aug 02 '17 at 14:42
  • @Slava, doesn't answer the plain question in the title. – SergeyA Aug 02 '17 at 14:43
  • If it freed the memory, then you'd never have much use for placement new – UKMonkey Aug 02 '17 at 15:39

4 Answers4

5

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".

eerorika
  • 232,697
  • 12
  • 197
  • 326
4

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.

SergeyA
  • 61,605
  • 5
  • 78
  • 137
  • I would just say "memory", not "physical memory" since most of the time it is *virtual memory* (not physical RAM) – Basile Starynkevitch Aug 02 '17 at 14:37
  • @BasileStarynkevitch, going too much into too deep. One might argue that virtual memory is also physical in a plain sense, since it is backed by RAM (or any other memory like MMC) or swap - both of which are quite physical. My point was that storage is material, so to say. I do not know how properly express this, I am afraid, we can not really define what 'material' means. – SergeyA Aug 02 '17 at 14:41
1

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.

Cory Kramer
  • 114,268
  • 16
  • 167
  • 218
1

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.

2785528
  • 5,438
  • 2
  • 18
  • 20
  • UB - in this case, it is the use of a dangling pointer, a pointer to an object that has been dtor'd – 2785528 Aug 02 '17 at 15:58