【发布时间】:2015-12-05 16:52:54
【问题描述】:
考虑三个这样的类:
class A {
int bar;
};
class B {
A* a;
public:
B(*A na)
: a(na)
{}
~B() {
a->bar = 0;
}
};
class Foo {
A* a;
B b;
public:
Foo()
: a(new A)
, b(a)
{}
~Foo() {
delete a;
}
};
创建Foo 的实例会导致Foo 带有指向A 的指针和带有相同指针的B。
当Foo的实例被删除时,指针a被删除,然后b的析构函数被调用,但~B试图访问a,~Foo中被释放,这会导致分段错误。
有没有办法在运行~Foo的主体之前调用b的析构函数?
我知道我可以通过将b 设为指针或将a 设为非指针来解决此问题。如果A 是抽象的,则后者不起作用,我想知道是否可以不使b 成为指针。
PS:A 和 B 都来自库,所以我无法更改它们的实现。
【问题讨论】:
-
当您说“使
a成为指针”时,我预计缺少的单词(您忘记输入)是“不是”,但缺少的单词应该是“智能”。明确的答案是a应该是一个智能指针,所以它会以正确的顺序被删除。 -
这并不能真正回答您的问题,但我建议只将 B 设为指针。您可以使用智能指针来完成您的要求,但我认为除非您有充分的理由,否则依赖基于成员顺序的破坏顺序是一种危险的做法,而且我认为这不是一个原因。最好只使它们成为指针并以正确的顺序破坏它们,并附上注释解释为什么必须按该顺序破坏它们。
-
@Gerald,设计显然必须取决于构造顺序。使用智能指针不会产生对序列的新依赖。它仅取决于破坏顺序与构造顺序相反,这是语言中内置的规则(除非您强制执行其他操作,就像 OP 通过使用非智能指针所做的那样)。
-
@JSF - 如果 ctor/dtor 的顺序像这样重要,我更愿意明确说明,而不是依赖于成员顺序。是的,该规则是内置在语言中的,但这并不意味着您想为了方便而依赖它。特别是在团队环境中,您只是在为这种设计找麻烦。即有一天可能会出现一个编码标准,成员应该按字母顺序声明,也许他们甚至使用一种工具来使代码达到标准,这会被打破,谁知道要花多长时间才能弄清楚发生了什么。 (去过那里。)
-
如果他们真的被命名为 A 和 B 他会没事的,但不知何故我怀疑:)
标签: c++ pointers destructor