How do I prevent deletion of a pointer without using const?
I have a class that contains a vector of object pointers. I have a GetObject(..) function in that class that looks through the vector, finds the object开发者_如何学运维 desired, and returns a pointer to it. However, if the user of the class does a delete() on that returned pointer, my program will crash because the vector still has a pointer to that, now invalid, object. So, in my GetObject() class, I can return a const pointer, but that doesn't solve the problem because you can still delete the object. The object is mutable so I can't return a pointer to a const object. I suppose I could prevent deletion by returning a reference to the object but I have my function returning NULL if there is an error. I guess I can pass back the object reference via the parameters and then return and error number like this
//-1 on object on found. 0 for success. Object is passed back in
// the function parameter result.
int MyObject::GetObject(int object_id, Item& result)
Is this the best solution for such a situation?
The best way to solve this problem is to use a shared-ownership smart pointer like shared_ptr
, which you can find in Boost, C++ TR1, and C++0x.
A smart pointer is a container that manages the lifetime of your dynamically allocated object for you. It takes responsibility for delete
ing the object when you are done using it.
With a shared ownership smart pointer, you can have multiple smart pointers that all share ownership of the dynamically allocated object. A reference count is kept that keeps track of how many smart pointers have ownership of the object, and when the last owning smart pointer is destroyed, the dynamically allocated object is delete
d.
It is extremely difficult to manage resources manually in C++, and it's very easy to write code that looks correct and works right most of the time but that is still not correct. By using smart pointers and other resource-owning containers (like the standard library containers), you no longer have to manage resource manually. It is significantly easier to write correct code when all of your resource management is automatic.
Automatic resource management in C++ is accomplished using a design pattern called Resource Acquisition is Initialization (RAII), which is arguably the most important design pattern you as a C++ programmer should become familiar with.
Anybody in your code could also try to de-reference NULL. You going to stop them doing that too? If your container owns the object, and you make this clear (returning a raw pointer is usually pretty clear or mention in docs), then anyone who deletes it, the result is their own fault. The only way that you could guarantee the prevention of the deletion of the object is to prevent the user from ever gaining a native reference or pointer - in which case they just can't access the object.
Who are clients of your class? If they are not your mortal enemies you could just ask them nicely not to delete the object. Otherwise, there will always be a way for "them" to mess you up.
Okay, one possible solution is to make destructor private. That will prevent everyone from deleting the object. But then the object has to delete itself (delete this
) somehow, maybe through some function called DeletObjectButDontBlameMeIfAppCrashes
. If the owner is some other class then you can set the destructor to protected and owner class as friend of this class.
You should return a reference to the object. There are two ways to handle the case when there is no object found.
First, you can use the Null Object Pattern in order to implement a special value for that case. That might not make sense for your case though.
The other way is to split it up into two methods, one which can be used to check if an appropriate element exists, and one to retrieve it.
Many STL-containers or algorithms implement both of these, either by returned a past-the-end iterator, or by having empty() returns false
as a prerequisite of calling a method like front
or back
.
If you can use the boost libraries, smart pointers can be used to ensure that pointers stay valid. Essentially, each reference to a smart pointer increases its "use count" by 1. When the reset
function is called on a reference, the reference goes away and the use counter decrements. As long as some object is still holding on to a smart pointer, the reference will be valid. Note that the other classes will be able to change what its pointing to, but can't delete it.
(My description deals mainly with smart pointers specifically - the different types of pointers vary a little, but the general idea remains the same).
精彩评论