0

For a memory manager that I am writing in C++ as a proof of concept, in order to keep track of allocated objects I am allocating memory with malloc() in a function, then returning the pointer to that memory and using the placement new operator. Then, to track when the object is deleted, I pass the pointer into another function to call free() on the pointer.

However, since I am using free() instead of delete, the object's constructor is not automatically called like it usually is, so I have to call it myself. Also, since the memory manager is designed to work with any object, it is conceivable (and even likely) that at some point in it's lifetime it will have to free an object that potentially has multiple parent classes or is deep within an inheritance tree.

My initial solution to this would be to call the base objects destructor, which would call all of the child destructors (if this question is to be believed), but since the objects could literally be anything and have any set of inheritance, there is no way to know what the true base class for it is.

So my question is: will explicitly calling the child classes destructor automatically call all of the base destructors as well, like with delete, or is there no way to easily do this?

Community
  • 1
  • 1
sm81095
  • 290
  • 1
  • 6
  • 18
  • 2
    There is no difference in the behaviour of an automatic call of the destructor when compared to a manual call of the constructor (at least, none that I'm aware of). Proving that (with Standardese) might be tricky, though. – dyp Oct 24 '14 at 23:47
  • It would be very easy for you to write some code to find out. – Paul Rooney Oct 24 '14 at 23:48
  • 3
    @PaulRooney That doesn't give you any guarantees. – dyp Oct 24 '14 at 23:49

1 Answers1

3

Yes, that's guaranteed. C++14 [class.dtor]/8:

After executing the body of the destructor and destroying any automatic objects allocated within the body, a destructor for class X calls the destructors for X’s direct non-variant non-static data members, the destructors for X’s direct base classes and, if X is the type of the most derived class (12.6.2), its destructor calls the destructors for X’s virtual base classes.

Specifically, for any type T you can always do this:

void * addr = ::operator new(sizeof T);
T * p = ::new (addr) T(/* ctor args */);
p->~T();                                    // !
::operator delete(addr);

Or, if you didn't want to invoke an allocator:

{
    std::aligned_storage_t<sizeof(T), alignof(T)> storage;
    T * p = ::new (static_cast<void *>(std::addressof(storage))) T(/* args */);
    p->~T();
}
Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • I actually have two quick questions about that. 1. This is for C++14, but is it also guarenteed for C++11, which I am using? 2. This says it will do that, but it doesn't explicitly say this will happen for explicit calls, so is that guarenteed or is this talking about `delete` only? – sm81095 Oct 24 '14 at 23:50
  • 1
    @sm81095: 1) yes, 2) it's not talking about `delete`; it's talking about destructors. – Kerrek SB Oct 24 '14 at 23:53
  • Ok, awesome! Thanks for the quick and straightforward answer. I'm going to be doing a lot of testing with this, but since it's part of the standard I'm expecting everything to work. – sm81095 Oct 24 '14 at 23:58
  • 1
    @sm81095: Forget about that even. This is such a profound core part of the entire object model of the language that it's completely inconceivable that compiler would get any part of this wrong. – Kerrek SB Oct 24 '14 at 23:59