我有一个C ++类层次结构,如下所示:
class A;
class B
{
public:
B( A& a ) : a_( a )
{
};
private:
A& a_;
};
class MyObject
{
public:
MyObject() : b_( a_ )
{
};
private:
A a_;
B b_;
};
偶尔会发生在B的析构函数中,我会得到与其A引用相关的无效访问异常。看来A在B之前被销毁。
使用类成员初始化其他成员是否存在固有的错误?是否无法保证破坏的顺序?
谢谢, PaulH
答案 0 :(得分:6)
编辑:我错过了你问题的MyObject
部分,所以我的原始回答可能没有多大帮助。我想你的问题在于你没有发布的代码,精简的例子应该可以正常工作。
类B
不“拥有”通过引用传递的对象,因此对象a
和b
具有不同的生命周期。如果B::a_
引用的对象被销毁,B
的析构函数将访问无效的引用。
一些代码来解释我的意思:
class A;
class B {
public:
B(A a) : a_(a) {} // a is copied to a_
~B() { /* Access a_ */ }
private:
A a_;
};
class C {
public:
C(A& a) : a_(a) {} // a_ is a reference (implicit pointer)
// of an external object.
~C() { /* Access a_ */ }
private:
A& a_;
};
int main(int argc, char** argv) {
A* a = new A();
B b(*a);
C c(*a);
delete a;
// Now b has a valid copy of a, c has an invalid reference.
}
答案 1 :(得分:6)
在上面的代码中,销毁订单已明确定义 销毁订单与创建订单相反 创建顺序是成员在类中声明的顺序 所以在这种情况下:
Default Construction:
a_: constructed first using default constructor.
b_: constructed using a valid a_ passed to the constructor.
Destruction:
b_: destroyed first. The destructor can use the reference to a
As long as the object has not been copied (see below)
a_: destroyed second.
但如果使用复制构造函数复制对象,则可能存在问题。
以下复制构造函数由编译器定义:
MyObject::MyObject(MyObject const& copy)
:a_(copy.a_)
,b_(copy.b_)
{}
所以你可能在这里遇到潜在的问题。由于副本将包含一个对象'b_',其中包含从另一个对象复制的引用。如果另一个对象被销毁,那么这个'b_'将有一个无效的引用。
答案 2 :(得分:5)
a_应该在b_之前构造,b_应该在a_之前被破坏,基于你在MyObject中定义它们的顺序。