Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/140.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
析构函数顺序 我有一个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_; };_C++ - Fatal编程技术网

析构函数顺序 我有一个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_; };

析构函数顺序 我有一个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_; };,c++,C++,偶尔,在B的析构函数中,我会得到与A的引用相关的无效访问异常 使用类成员初始化其他成员是否存在固有的问题?难道不能保证销毁的顺序吗 谢谢, PaulH编辑:我错过了你问题中的MyObject部分,因此我最初的答案可能不会有多大帮助。我猜你的问题在于你没有发布的代码,精简的示例应该可以很好地工作 类B不“拥有”通过引用传递的对象,因此对象a和B具有不同的生命周期。如果B::a引用的对象被销毁,B的析构函数将访问无效引用 一些代码来解释我的意思: class A; class B { publi

偶尔,在B的析构函数中,我会得到与A的引用相关的无效访问异常

使用类成员初始化其他成员是否存在固有的问题?难道不能保证销毁的顺序吗

谢谢,
PaulH

编辑:我错过了你问题中的
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.
}

根据您在MyObject中定义的顺序,a应该在b之前构造,b应该在a之前销毁。

在上面的代码中,销毁顺序定义得很好。
销毁顺序与创建顺序相反。
创建顺序是成员在类中声明的顺序。
因此,在这种情况下:

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_u”将有一个无效的引用。

Hum,你的意思是在b中有一个析构函数对a做了一些事情吗?构造顺序遵循声明顺序,销毁顺序颠倒。在MyObject示例中,这意味着a_u应该在b_u之前构造,a_u应该在b_u之后销毁。您看,您是对的,根据定义,B不拥有a,但是,根据定义,MyObject应该保证正确的构造和销毁顺序。是的,我同意Eric,我认为问题中的代码a没有问题-MyObject中的成员是按正确的顺序声明的,这样它就不会崩溃。问题一定在别处。谢谢你的确认。这是破坏时给你的全部代码吗?你能给我们看看main()吗?问题是编译器的泛型复制构造函数。有关详细信息,请参见下面的答案。