is it required by the standard to call non-trivial destructor when you know that in this specific case the destructor is a noop ?
is the code likely to be broken by compliers if the destructor is not called ?
the use case is a class that contain a dynamicly allocated pointer. by default this pointer is obtained by new
in the constructor. this class can also get its dynamicly allocated pointer from an allocator. the class keeps track of how it obtained its pointer and calls delete
in the destrucor if the pointer was obtained by new
and nothing if it was obtained by the allocator because the allocator will free the memory. the data stored in the dynamic memory is only trivial type so their destructor doesn't need to be called.
so the question is do i still need to call the destructor on the class if i know that it obtained its pointer via the allocator so the destructor is a noop ?
this is a minimal simplified example everything not directly related to the issue was removed.
struct Allocator {
void* ptr = nullptr;
void* Allocate(size_t size) {
ptr = malloc(size);
return ptr;
}
~Allocator() { // allocator will cleanup
if (ptr)
free(ptr);
}
};
struct C {
int* ptr;
bool need_cleanup;
C() {
ptr = new int[10];
need_cleanup = true;
}
C(Allocator& A) {
ptr = (int*)A.Allocate(10 * sizeof(int));
need_cleanup = false;
}
~C() { // non-triviall because user-defined.
if (need_cleanup)
delete[] ptr;
// noop if need_cleanup is false.
}
};
int main()
{
Allocator A;
alignas(C) char buffer[sizeof(C)];
C* c = new(buffer) C(A);
/// is it required to call c->~C();
}
A class has a non-trivial destructor if it either has an explicitly defined destructor, or if it has a member object or a base class that has a non-trivial destructor.
No. You never need to explicitly call a destructor (except with placement new ). A class's destructor (whether or not you explicitly define one) automagically invokes the destructors for member objects. They are destroyed in the reverse order they appear within the declaration for the class.
A destructor has the same name as the class, preceded by a tilde ( ~ ). For example, the destructor for class String is declared: ~String() . If you do not define a destructor, the compiler will provide a default one; for many classes this is sufficient.
Destructor neither requires any argument nor returns any value. It is automatically called when object goes out of scope. Destructor release memory space occupied by the objects created by constructor. In destructor, objects are destroyed in the reverse of an object creation.
No.
For an object of a class type with a non-trivial destructor, the program is not required to call the destructor explicitly before the storage which the object occupies is reused or released; however, if there is no explicit call to the destructor or if a delete-expression (
[expr.delete]
) is not used to release the storage, the destructor shall not be implicitly called and any program that depends on the side effects produced by the destructor has undefined behavior.
[basic.life]
You are not depending on any side-effects of ~C
, so you don't have undefined behavior.
N.B. you should probably placement new[]
your A.Allocate
'd int[10]
C(Allocator& A) {
ptr = new (A.Allocate(10 * sizeof(int))) int[10];
need_cleanup = false;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With