Assume the following struct:
template <typename T>
struct A{
T* pointer;
void clearData(){
//delete data pointer is pointing to
data->~T(); //call destructor?
pointer = nullptr;
}
};
If I want to provide a function that clears the Data where pointer is pointing to - how would I go about this? I am aware of the new/delete, new[]/delete[] and malloc()/free() combinations but since T is templated I dont't know if the data was allocated using new, new[] or malloc(). From my understanding the destructor should always free up the allocated memory. So if I explicitly call the destructor there should be no memory leaks (if the destructor of the object is implemented correctly).
Are my assumptions correct or are there cases where this could lead to problems? If so please provide an example so I get a better understanding of the issue.
Note: Answers like "you should use smart pointers because explicitly calling the destructor is bad practice" are not helpful as I am trying to understand WHY it would cause issues in my case. And I see explicit destructor calls as a valid option if it can't lead to any issues.
No. Destructor should release owned resources. It is not clear that
Aowns anything, especially if it didn't allocate the resource on its own, but got it from somewhere else. And resources are not just allocated memory (could be e.g. open file handle), but that's not really related to the topic.Absolutely not. You are not allowed to call destructor of an object unless it was created with placement
new. And if it was, calling destructor will do what~T()does, but will do nothing to the memory it was occupying, which likely still needs to be released.It's not bad practice, it's straight up Undefined Behaviour (except for that one case mentioned earlier).
In your case,
Ashould not take ownership ofdataand make it clear in documentation that it wants a handle toTwhich will not be released in any way.If you really think
Ashould owndata, you need to also accept a deleter that will be able to releasedataproperly, because only the caller has knowledge on how to release it correctly (if it needs releasing at all) - just likestd::unique_ptrdoes. And at this point, you could also just acceptstd::unique_ptrand forget about the issue altogether.