Is it bad practice to assign one pointer to another?

For example,
int *p = new int;
*p = 8;
int *q;
q = p;

Now q points to the same int as p. Say p and q are put into a Container that has ownership. When the container deletes p and q, there might be a problem: "delete q" is valid, but after that q points to nothing and "delete q" is invalid!

Similarly, if q is allocated:
int *q = new int;
q = p;
Another potential problem might occur: the space assigned to q might not get freed and leads to memory leak.

This problem might be solved if "delete" set is object pointer to NULL, but this is not C++ default. Even if user implements this, after setting p=NULL, "delete" has to find q (and any other possible pointers pointing at the same address as p), and set it (and them) to NULL.

Are the problems above real problems?
If yes, does it imply that it is normally bad practice that multiple pointers pointing to the same address (like by pointer assign)?
Yes the above are real problems.

assigning a pointer isn't necessarily a bad thing, though. It all depends on the context and whether or not you have clear ownership constructs defined.
If "int" type is sub-class of "Object" which has a member function of "IsNull()", that would solve this problem.

But it seems that "int" is a C++ build-in type and do not has "IsNull()". If I remember correctly, Java can test whether a "Integer" object is NULL, but Java does not has pointer at the first place...
As Disch said, you have to define who/what has ownership and mandate it to the furthest extent possible. Of course it does depend on context but generally: If you can use [const] references rather than pointers, do it. If you can just use a local variable on the stack, do it. If you can use a smart pointer, such as boost::shared_ptr, do it. If you can use an auto_ptr, do it. The more automation of resource management the better.

For more information, research exception safety. It's RAII technique is very useful even when exceptions are not present.
Last edited on
Thanks for your reply.

I did a little research, and found that the only "null pointer exception" in C++ is when new fails to allocate memory:
int *p = new int
Then p should be null and you can throw an exception.

Let me ask the question another way: if you know p is defined as a pointer to an integer, how can you know it is actually allocated a space and has a integer to point to, so it's safe to use *p? How can a "null pointer exception" be thrown in this case?

Or, how can you know the pointer you are using now has not been freed? (This won't cause a compile error, but should raise run-time error.)

If I understand you correctly, you mean my "null pointer" problem should occur at the first place, if the develop is careful enough ... (but it would seem to me that it is very hard too be careful enough when you assign a pointer to another directly.)

I guess it would be OK if the pointer is not pointing to int, char, double or string - the 4 basic build-in types. If it points to a user-defined type derived from the class "Object", the "IsNull" function should normally be implemented so that it is possible to call " *p.IsNull()" to check if pointer p has already been deleted.
Last edited on
if you know p is defined as a pointer to an integer, how can you know it is actually allocated a space and has a integer to point to, so it's safe to use *p? How can a "null pointer exception" be thrown in this case?


If all you have is the pointer and no other information about the allocated buffer, then there is no way to know.

This is one of the many reasons why using pointers directly is "evil" and why container classes are generally preferred.

Generally... to use pointers safely, you need to know other information (such as the number of elements allocated, whether or not anything at all is allocated, who the owner is, etc). All this information can be bundled in a class that you pass around instead of passing around the pointer.

(but it would seem to me that it is very hard too be careful enough when you assign a pointer to another directly.)


It is kind of... but not really. It depends entirely on the circumstance.

If A owns the pointer and gives the pointer to B. Then you just need to be sure that A's lifetime is as long or longer than B's.

If A and B have independent lifetimes and there's no way to know whose life will end first, then you probably don't want to pass pointers around this way. If A dies (and frees the pointer) while B is still alive and using the pointer, you're hosed.

I guess it would be OK if the pointer is not pointing to int, char, double or string - the 4 basic build-in types.


string isn't really a built in type. It's a complex class. There are also many other types, like float, short, long and bool. Not counting unsigned counterparts, extended types (long long), and bitfields.

If it points to a user-defined type derived from the class "Object", the "IsNull" function should normally be implemented so that it is possible to call " *p.IsNull()" to check if pointer p has already been deleted.


This doesn't work anyway.

An object can't check itself to see if it's already been deleted because if it's already been deleted then it's too late and there's nothing it can check.

Unless I'm missing something, I don't see how an IsNull function could be implemented legally in C++. Not unless it's incredibly complex and impractical.
Just a few things Disch failed to mention:
I did a little research, and found that the only "null pointer exception" in C++ is when new fails to allocate memory:
int *p = new int
Then p should be null and you can throw an exception.
There's no such thing as a "null pointer exception". If an invalid pointer is dereferenced, a non-standard behavior will be triggered.
In that example, if new failed to allocate memory, std::bad_alloc will be thrown (and p will thus have no value).

There are also many other types, like float, short, long and bool. Not counting unsigned counterparts, extended types (long long), and bitfields.
And void. And other pointers. Technically, there's an infinite number of basic types.

Unless I'm missing something, I don't see how an IsNull function could be implemented legally in C++. Not unless it's incredibly complex and impractical.
It depends on what "null" means. Using the semantics OP is talking about, such an IsNull() can't be implemented without knowing details about the (language) implementation and system. It can be a member function if the implementation allows calling member functions using invalid pointers (((T *)0)->IsNull()), but it has to be global function otherwise.

Newbies tend to get hung up on these minutiae. It's hard, but it's actually possible for the programmer to know at compile time at any given point in a program whether a pointer needs to be deleted.
A couple guidelines:
1. The rule of gold: Generally speaking, pointers should be freed at the same level they were allocated.
2. Transfer ownership only as a last resort.
3. Take references whenever possible.
4. Never assume a function you didn't write transfers ownership of returned pointers. A memory leak is slightly better than memory corruption (but that's no excuse to not read the documentation). E.g. std::string::c_str().
Thanks for the reply from helios and Disch. I learned a lot from you guys.

I have to apologize that my question may seem naive and non-practical. Indeed, I am not a C++ guru (though have known it for years and used it now and then).

This question comes to my mind when I read a Data Structure and Algorithm book (by Bruno @ Waterloo) about the Container of indirect containment. The destructor is implemented such that if the container has ownership, the contained pointers should be deleted. Then, if in the container there happens to be multiple pointers pointing to the same location, memory corruption occurs - to prevent this problem, I wished there is a way to test if a pointer has been allocated before delete it.

If I understand helios and Disch correctly, a good programmer should never let the above problem occur. If the container has shorter lifetime than its containing pointers, the container should not have ownership; if the container is created before the pointers and do have ownership, then maybe it's just non-sense to create pointers pointing to the same location.
If you're passing around ownership, or if the lifetime of the owner is undeterminable, you really should consider using something like a smart pointer (like boost::shared_ptr).

They let you pass around ownership as much as you like, and the pointer is only deleted once all owners are done with the pointer.
Topic archived. No new replies allowed.