template<typename T>
someclass<T>& operator=(const someclass<T>& other)
{
typename std::vector<T *>::const_iterator rhs;
typename std::vector<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));
}
}
}
正如您在评论中看到的那样,我忘了清除数组中的旧指针。当我第二次调用赋值运算符时,我得到glibc错误抱怨双重释放。提供的唯一信息是删除的地址。
这让我想到如何处理这类已删除的指针 - 当你不想再删除它们时,当你这样做时,肯定是一个错误。您不能将它们设置为NULL,因为另一个删除是正确的。您不希望保留该值,因为可以将内存位置分配给新创建的对象。
调试的好处是一些值,比如INVALID,你分配给这些指针说“在这个指针上调用delete是一个错误”,而不是NULL,它说“在这个指针上调用delete什么都不做”。有这样的事吗?
答案 0 :(得分:6)
没有。当你想拥有所有权语义时,更好的想法是不使用原始指针。如果您将data
类型设为boost::ptr_vector<T>
或std::vector<std::unique_ptr<T>>
,则无需手动管理指针的生命周期,问题就会消失。
您的容器不能正确支持多态对象,因为您提供的赋值运算符会在将容器中的对象分配给另一个容器时对其进行切片。更好的解决方案可能是拥有std::vector<T>
。如果你不指望指针容器的其他属性(例如指向元素的指针的无效,或者可能更快的排序操作),这将是合适的。
答案 1 :(得分:2)
此问题的解决方案是编写不包含任何删除的代码。尽可能使用shared_ptr
。当您拥有拥有多态对象的容器时,您也可以使用Pointer Container。