Destructor order
I have a C++ class hierarchy that looks s开发者_如何学Goomething like this:
class A;
class B
{
public:
B( A& a ) : a_( a )
{
};
private:
A& a_;
};
class MyObject
{
public:
MyObject() : b_( a_ )
{
};
private:
A a_;
B b_;
};
Occasionally, it will happen that in B's destructor I will get invalid access exceptions relating to its reference of A. It appears that A is destroyed before B.
Is there something inherently wrong with using class members to initialize other members? Is there no guarantee of the order of destruction?
Thanks, PaulH
EDIT: I missed the MyObject
part of your question so my original answer will probably not be of much help. I guess your problem lies in the code you did not post, the stripped-down example should work fine.
Class B
does not “own” the object passed by reference, therefore the objects a
and b
have different life cycles. If the object refered to by B::a_
is destroyed, B
's destructor will access an invalid reference.
Some code to explain what I mean:
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.
}
In the code above the destruction order is well defined.
The destruction order is the reverse of the creation order.
The creation order is the order the members were declared within the class.
So in this case:
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.
But you have a potential problem if you make a copy of the object using the copy constructor.
The following copy constructor is defined by the compiler:
MyObject::MyObject(MyObject const& copy)
:a_(copy.a_)
,b_(copy.b_)
{}
So you may have a potential problem here. As the copy will contain an object 'b_' that contains a reference that was copied from another object. If the other object is destroyed then this 'b_' will have an invalid reference.
a_ should be constructed before b_, and b_ should be destructed before a_, based on the order you have defined them in MyObject.
精彩评论