我正在寻找一种清洁指针的正确方法。 这里是示例代码:
class Parent {
protected:
int m_Var;
public:
Parent() : m_Var(0) {}
virtual ~Parent() {}
void PubFunc();
};
class Child : public Parent {
protected:
bool m_Bool;
public:
Child() : m_Bool(false) {}
virtual ~Child() {}
void ChildFunc();
};
void RemoveObj(Parent **ppObj)
{
*ppObj->PubFunc();
delete *ppObj;
ppObj = NULL;
}
int main()
{
Parent* pPObj = NULL;
Child* pCObj = NULL;
pPObj = new Parent();
pCObj = new Child();
RemoveObj(&pPObj);
RemoveObj(&pCObj); // This is line 33
return 1;
}
但是编译器给出了错误:
classes.cpp:33: error: invalid conversion from ‘Child**’ to ‘Parent**’
classes.cpp:33: error: initializing argument 1 of ‘void RemoveObj(Parent**)’
答案 0 :(得分:12)
有很多方法可以正确处理内存。
接近你的例子的是:
template <typename T>
RemoveObj(T **p)
{
if (p == NULL) return;
delete *p;
*p = NULL;
}
此外,您可能希望使用std :: auto_ptr。它看起来像是:
int main()
{
std::auto_ptr<Parent*> pPObj(new Parent);
std::auto_ptr<Child*> pCObj(new Child);
// no deletes needed anymore
答案 1 :(得分:3)
说实话:
Child是Parent的子类,这意味着Child *可以替换为Parent *
BUT
Child *不是Parent *的子类,因此意味着Child **不能替换为Parent **
“儿童”和“儿童*”的类型不同。
答案 2 :(得分:3)
您需要做的是取消所有指向您刚刚删除的对象的指针。指针的想法是存在多个指针存储同一对象的地址。如果没有,没有理由使用裸指针,所以你试图捕获的模式不是很有用 - 但你远不是第一个尝试这个的人。正如其他答案所提到的,处理指针的唯一方法是仔细控制对它们的访问。
你的问题标题绝对正确!这是有充分理由的。指针标识存储特定类型的对象的位置。指向指针的指针使您能够更改指针指向的对象。
void Foo(Parent **pp)
{
*pp = new OtherChild();
}
您的Child
班级来自Parent
,我的OtherChild
班级也是如此。假设编译器允许您这样做:
Child *c = 0;
Foo(&c);
你希望它可以工作,但如果有,那么我们现在有一个Child
指针c
实际上指向OtherChild
的实例。谁说这两种类型兼容?
同样,这是一个非常频繁的误解 - 它在这里反复出现其他语言,特别是关于C#中的List<Parent>
和List<Child>
。
答案 3 :(得分:2)
你不需要一个包装用于删除,保持简单:
int main()
{
Parent* pPObj = NULL;
Child* pCObj = NULL;
pPObj = new Parent();
pCObj = new Child();
delete pPObj;
delete pCObj; // This is line 33
return 1;
}
请记住,在使用RemoveObj
删除数组类型对象时会遇到问题(因为您总是使用标量delete
)。另一种选择当然是传递一个标志,表示你想要{{1}}。但正如我所说:亲吻。
答案 4 :(得分:2)
如果您的问题是处理内存和资源,最好的建议是完全忘记您的方法并使用智能指针。 std :: auto_ptr 或 boost :: shared_ptr 将是一个起点。
如果使用智能指针保存所有堆分配的资源,则代码将更加健壮。
答案 5 :(得分:1)
你可以从书中找到一些有用的信息&lt;
答案 6 :(得分:0)
可能是我找到的最简单的解决方案:
#define __REMOVE_OBJ(pObj) RemoveObj(pObj); pObj = NULL;
请拨打这个:
__REMOVE_OBJ(pPObj);
__REMOVE_OBJ(pCObj);
但我自己并不喜欢......
答案 7 :(得分:0)
关于make shared_ptr not use delete
的讨论共享指针将确保您应该在需要时进行清理,并且不会访问被破坏的内容。此外,您可以专门化并提供替代销毁方法。
boost::shared_ptr<T> ptr( new T, std::mem_fun_ref(&T::deleteMe) );