如果我的类有一个可以由类客户端设置的指针,我应该如何处理删除?
示例:
class A {
};
class B {
public:
void setA(A* a) {
this->a = a;
}
private:
A* a;
};
如何成为班级B
的析构函数?它应该删除a
吗?正如我所看到的,用户可以通过两种方式设置此指针:
... // Assume B object b being created elsewhere
A aObj;
A* aPtr = new A();
b.setA(&aObj); // It is not OK to use delete, and class member will
// point to invalid memory location once aObj goes out
// of scope
b.setA(aPtr); // Using new will make the pointer available even after
// this block of code
...
那么删除b的正确方法是什么?我应该始终在new
方法中执行set
吗?
答案 0 :(得分:7)
B类的析构函数应该如何?它应该删除吗?
你,该类的作者,决定它的语义。不要考虑指针,引用和delete
。从设计的角度思考:A
和B
之间的关系是什么? B
需要A
为什么?
两种常见的关系类型是委托和组合。委托意味着客户端代码使用setA
成员使实例知道可能用于进一步使用的其他B
实例。组合意味着setA
成员用于初始化实例的内部部分。
委派的一种可能实现是使用成员指针。我建议传递一个setA
的引用来分配给那个指针;它回避了检查0
的问题,并使客户端代码明白没有所有权问题需要处理。这与多态类型兼容。
组合的一种可能实现是使用A
成员,并通过引用传递给const或按值分配给它。另一种方法是使用智能指针,特别是如果A
是多态使用的话。通过智能指针传递是最简单的事情 - 但你必须检查0
和/或记录演员。
无论您决定使用什么(无论如何都不必在此列表中),请使用代码作为工具来实现您的目的或设计。不要让代码决定你的想法。
在我的所有示例实现中,您不必在析构函数中执行任何特殊操作。
答案 1 :(得分:2)
你真的应该真的没有这样的课程。相反,使用资源管理容器(如shared_ptr
或unique_ptr
)来保存指向动态分配对象的指针。
正如您可以轻松看到的那样,如果您在整个地方随机分配动态对象,您将无法跟踪谁应该负责的事情。怎么样复制和分配你的课程?那么构造函数中的异常呢?不要这样做。
答案 2 :(得分:1)
我认为通常会有3种情况,请参阅下面的代码:
//class B doesn't own a
class B {
public:
void setA(A& a) {
m_a = a;
}
private:
A& m_a; //Only a reference , so need to worry about delete
};
//class B owns A
class B {
public:
void setA(std::auto_ptr<A>& a) {
m_a.reset(a.release());
}
private:
boost::scoped_ptr<A> m_a; //m_a got deleted when instance of B lifetime end
};
//class B shared A with someone else
class B {
public:
void setA(boost::shared_ptr<A>& a) {
m_a = a;
}
private:
boost::shared_ptr<A> m_a; //m_a got deleted when no one need this pointer anymore(reference counting reduced to 0)
};
答案 3 :(得分:0)
从外观上看,您正在尝试在B类中创建对A对象的引用。
要正确清理B,您必须先检查A是否为空。有点像...
~B()
{
if (A)
{
delete A;
A = 0;
}
}
请记住,这也删除了类之外的A对象,因为它们引用了相同的内存。因此,在这种情况下,如果删除了A对象,则非常容易引用指向无效内存的指针。
我不会将它与btw的局部变量一起使用,因为当它超出范围时你将丢失它的地址。但是,另一方面是本地指针..那么,一旦离开创建A的范围,就不必担心引用无效内存。
答案 4 :(得分:0)
你有一个设计决定。谁应该拥有这个对象?
setA
将所有权传递给B.B的析构函数应删除A. 智能指针的第三个选项是最简单和最可靠的,但所有3个选项都可以使用。诀窍是挑选一个并慎重考虑它。
答案 5 :(得分:0)
在设计分析期间,您必须回答以下问题: