Reputation: 24028
How do I check if a variable, specifically a pointer, is defined in C++? Suppose I have a class:
class MyClass {
public:
MyClass();
~MyClass() {
delete pointer; // if defined!
}
initializePointer() {
pointer = new OtherClass();
}
private:
OtherClass* pointer;
};
Upvotes: 4
Views: 16591
Reputation: 208456
The real answer is that of litb, but I just wanted to make a side comment. Using smart pointers (in this case std::auto_ptr suffices) takes care of the problem and has the advantage that you will not need to remember to delete the pointer in the destructor. In fact default destructor (generated by the compiler) will take care of memory resources.
Making the comment even more general, you class should declare assignment operator and copy constructor marked as private (and not defined) or manually defined to avoid double deletes of the pointer. Compiler provided operator== and copy constructor will just copy the pointer and eventually you will get into a double delete. I write this here since that is also something to take into account if you use std::auto_ptr with the added strangeness of the copy semantics in auto_ptr.
Upvotes: 1
Reputation: 264689
The whole point of the constructor is that after it has completed all member variables are correctly defined. In this case NULL is a valid initial value.
Calling delete on NULL is well defined.
More normally though you would expect the constructor to define the value of the RAW pointer. Also because your object contains a RAW pointer and obviously owns it (it is deleting it, this implies ownership) you MUST also make sure you override the compiler generated versions of Copy Constructor and Assignment Operator.
class MyClass
{
public:
MyClass()
:pointer(NULL) // valid value.
{}
~MyClass()
{
delete pointer; // This is fine.
}
void initializePointer() // Missing return type
{
pointer = new OtherClass();
}
private:
MyClass(MyClass const& copy); // If you don't define these
MyClass& operator=(MyClass const& copy);// two the compiler generated ones
// will do nasty things with owned
// RAW pointers.
OtherClass* pointer;
};
Alternatively you can use one of the standard smart pointers. Probably std::auto_ptr<> unless you really want to make the object copyable.
Upvotes: 4
Reputation: 340446
An additional answer that no else has mentioned yet is to use a smart pointer object instead of a raw pointer. Depending on how the pointer is subsequently used, std::auto_ptr
, boost::shared_ptr
, or a number of other smart pointer classes might be appropriate here. boost::scoped_ptr
might also work if you change how initializePointer()
works a little bit.
That way the smart pointer takes care of remembering whether it's valid or not and deleting itself when the containing object is destroyed:
class MyClass {
public:
MyClass();
~MyClass() {
}
initializePointer() {
pointer.reset( new OtherClass());
}
private:
std::auto_ptr<OtherClass> pointer;
};
Upvotes: 1
Reputation: 507343
Why worry about checking for the pointers value? Just initialize it to a null pointer value and then just call delete on it. delete on a null pointer does nothing (the standard guarantees it).
class MyClass {
public:
MyClass():pointer(0) { }
~MyClass() {
delete pointer;
pointer = 0;
}
initializePointer() {
pointer = new OtherClass();
}
private:
OtherClass* pointer;
};
And everytime you call delete on it, you should set the pointer to a null pointer value. Then you are all fine.
Upvotes: 22
Reputation: 546073
In addition to checking for 0
(NULL
), one solution would be to refactor your code so you force the pointer to always be valid. This is not always possible, but in most cases, it's the best solution.
In your case (as in most other cases), this means initializing the pointer in the constructor (i.e. as soon as its lifetime starts) and destroy it at the end of its lifetime. Make the variable private
and don't allow direct write access to it to ensure that it will always stay valid.
This is an often used pattern in C++ and it effectively bounds the object lifetime of the pointee to the lifetime of your class. Sometimes, it might also be a viable solution to provide some kind of reset
that deletes the pointer and immediately re-initializes it. If this is written in an exception-safe way, you've also ensured that your pointer will never be invalid.
Do not create a bool
ean flag to keep track of your pointer's validity. This solution has no advantage, and many disadvantages, to setting the pointer to 0
.
Upvotes: 6
Reputation: 107042
You can't, AFAIK I know. A standard method is to set it to NULL when it contains no valid value. Leaving pointers around that point to invalid memory is bad practice under any circumstances. If you stick to this, you can always check for NULL to see if it's "defined" or not.
Upvotes: 1
Reputation: 40430
You should always initialize your pointers to NULL in your constructor; that way you can check in the destructor if it's been initialized. Also, it's more efficient to do it in the constructor's argument list like so:
MyClass::MyClass() : pointer(NULL)
{
}
MyClass::~MyClass()
{
if(pointer != NULL) { delete pointer; }
}
Likewise, you should also set the value to NULL when you delete it and check the value against null when allocating it, if the object is going to be re-initialized many times during the lifespan of your program. However, setting the value to NULL in the destructor won't make any difference, since the object is obviously going to be destroyed anyways.
The advantage of doing it this way (instead of saying "pointer = NULL;" explicitly in the constructor) is that the compiler is already implicitly doing an assignment like this for you. Doing a manual assignment makes it happen twice, which normally isn't a big deal except if you are making many instances of your class in a big loop or something.
Upvotes: 2
Reputation: 26341
I tend to initialize my pointer values to NULL on object construction. This allows a check against NULL to see if the pointer variable is defined.
Upvotes: 8