I have a class whose constructor
takes the address of an object as a parameter.
MyClass(OtherClass * otherClass);
In the Destructor
of this class I try to delete
the instance of OtherClass
.
~MyClass() {
if(otherClass != nullptr) {
delete otherClass;
}
}
The issue I'm having is when I call this constructor
I call it with an element from the stack
instead of from the heap
, thus I call it as below:
MyClass myClass(&otherObject);
so when the myClass
object goes out of scope I get an exception. How can I find out if my OtherObject
variable was declared on the stack
or the heap
? Or in other words, how can I know if I can delete
the object?
While there are system specific approaches which will probably be able to tell whether memory is from heap or from a stack, that actually doesn't really help: you may have got a pointer to a member of another object on the heap. The memory would be on the heap but you are still not responsible for deleting the object. Put differently: do not go down the path you are on!
The proper way to deal with the problem is to make the ownership semantics blatantly clear in the interface and go with that. There are essentially two directions you can take:
std::unique_ptr<OtherClass>
.delete
all of them. It becomes the responsibility of the caller to not pass pointers to objects managed elsewhere, e.g., to objects on the stack or member objects.There is sort of a hybrid approach where your class takes responsibility of objects some times but not always. However, the implementations of such an approach is really a combination of the two approaches above: you'd take a suitable smart pointer as constructor argument and it is the user's responsibility to make sure that the smart pointer is constructed appropriately by the user of your class. For example, your class could take a std::shared_ptr<OtherClass>
for which the normal construction will delete
the object. When the user wants to pass in a pointer to an otherwise owned object the std::shared_ptr<OtherClass>
would be constructed with a deleter which does not delete
the pointer. Here is a simple program demonstrating the two different management strategies for std::shared_ptr
:
#include <iostream>
#include <memory>
struct foo {
char const* name;
foo(char const* name)
: name(name) {
std::cout << "foo::foo(" << name << "): " << this << "\n";
}
~foo() {
std::cout << "foo::~foo(" << name << "): " << this << "\n";
}
};
int main() {
std::shared_ptr<foo>(new foo("heap"));
foo f("stack");
std::shared_ptr<foo>(&f, [](auto){});
}