template<typename T>
someclass<T>& operator=(const someclass<T>& other)
{
typename std::vector<T *>::const_iterator rhs;
typename std::vector<T *&g开发者_运维技巧t;::iterator lhs;
//identity test
//this->data is std::vector<T *>
for(lhs = this->data.begin(); lhs != this->data.end(); lhs++)
{
delete *lhs;
}
this->data.clear(); // this is what I forgot
this->data.reserve(other.data.size());
for (rhs = other.data.begin(); rhs != other.data.end(); rhs++)
{
if (NULL == *rhs)
{
this->data.push_back(NULL);
}
else
{
this->data.push_back(new T(**rhs));
}
}
}
As you can see in the comments, I forgot to clear out the old pointers in the array. When I invoked the assignment operator for the second time, I got glibc error complaining about double free. The only information provided was the deleted address.
This make me thinking about what to do with such class of deleted pointers - when you don't want to delete them again, and when you do, it is certainly an error. You cannot set them to NULL, because another delete would be correct then. You don't want to keep the value as the memory location can be assigned to newly created object.
What would be good for debugging is some value, like INVALID, which you assign to these pointers saying "invoking delete on this pointer is an error", instead of NULL, which say "invoking delete on this pointer does nothing". Is there something like this?
No. A better idea would be to not use raw pointers when you want to have ownership semantics. If you make the type of data
be boost::ptr_vector<T>
or std::vector<std::unique_ptr<T>>
then you will not have to manually manage the lifetimes of your pointers, and the problem will go away.
Your container does not properly support polymorphic objects, as the assignment operator that you have presented will slice the objects in the container when they are assigned to another container. An even better solution may be to just have a std::vector<T>
. This would only be appropriate if you were not counting on some other property of containers of pointers (such as the non-invalidation of pointers to elements, or potentially faster sorting operations).
The solution to this problem is to write code that does not contain any deletes. Use shared_ptr
where possible. When you have a container that owns polymorphic objects, you can also use Pointer Container.
精彩评论