C++ 在C++;?

C++ 在C++;?,c++,destructor,C++,Destructor,我试图理解在析构函数中允许做什么 声明:“对于具有非平凡析构函数的对象,在析构函数完成执行后引用该对象的任何非静态成员或基类会导致未定义的行为”。 以这种方式描述销毁序列:“对于用户定义或隐式定义的析构函数,在执行析构函数体后,编译器为类的所有非静态非变量成员调用析构函数” 这是否意味着,在下面的代码中,从其成员的析构函数调用方法是UB?或者“参考”标准指的是特定的东西 struct Foo { Foo(Callback cb) : cb_(cb) {} ~Foo() { //

我试图理解在析构函数中允许做什么

声明:“对于具有非平凡析构函数的对象,在析构函数完成执行后引用该对象的任何非静态成员或基类会导致未定义的行为”。
以这种方式描述销毁序列:“对于用户定义或隐式定义的析构函数,在执行析构函数体后,编译器为类的所有非静态非变量成员调用析构函数”

这是否意味着,在下面的代码中,从其成员的析构函数调用方法是UB?或者“参考”标准指的是特定的东西

struct Foo {
  Foo(Callback cb) : cb_(cb) {}

  ~Foo() {
    // body of Bar destructor finished at this moment;
    // cb_() calls Bar::call_me()
    cb_();
  }

  Callback cb_;
};

struct Bar {
  // pass callback with captured this
  Bar() : foo_([this]() { call_me(); }) {
  }

  void call_me() {
  }

  // foo is a member, its destructor will be called after Bar destructor
  Foo foo_;
};
另外,标准中的短语“析构函数完成后”到底是什么意思?在析构函数的主体完成之后?还是在所有成员和基类被销毁之后?

我认为最后一个问题的答案是理解什么是允许的,什么是不允许的关键。

条码的析构函数尚未完成,因此引用了条码的一个成员,实际上在其析构函数中调用条码的成员函数是可以的

调用超级对象的成员函数可能有点不稳定,因为成员函数可能会访问子对象,并且在调用成员函数时某些子对象可能已经被破坏,在这种情况下,访问被破坏的对象将导致未定义的行为。你的例子不是这样的

或者“参考”标准指的是特定的东西

struct Foo {
  Foo(Callback cb) : cb_(cb) {}

  ~Foo() {
    // body of Bar destructor finished at this moment;
    // cb_() calls Bar::call_me()
    cb_();
  }

  Callback cb_;
};

struct Bar {
  // pass callback with captured this
  Bar() : foo_([this]() { call_me(); }) {
  }

  void call_me() {
  }

  // foo is a member, its destructor will be called after Bar destructor
  Foo foo_;
};
我认为这意味着形成一个指针或一个子对象的引用。正如下面的示例中所做的那样


另外,标准中的短语“析构函数完成后”到底是什么意思?在析构函数的主体完成之后?还是在所有成员和基类都被销毁之后

后者


首先执行主体,然后析构函数调用子对象析构函数,然后析构函数完成。

编译和运行此示例可能会产生误导,因为我希望它工作得“很好”。如果
call\u me
将访问本身具有非平凡析构函数的
Bar
的成员,则问题可能更为明显。@magnize\u prime\u是\u 463035818,即使我没有看到问题。引用的段落清楚地说“在析构函数完成之后”,而不是“在析构函数的主体完成之后”。只要
call\u me
只访问尚未销毁的Bar成员(也就是说,在
foo\uuu
之前定义,一切都很好。第一段仅表示在
foo
被销毁后,您无法访问其成员或调用其方法。第二段表示,除了用户定义的析构函数中的操作之外,用户析构函数完成后,成员析构函数始终会自动调用。因此,“析构函数完成后”指“析构函数主体完成后”“+所有自动析构函数都已完成。@最大的\u prime\u是\u 463035818,我希望示例尽可能简单。通过main函数、includes和using语句,此示例编译并执行得很好。核心案例是
my\u class*ptr=new my\u class;delete ptr;ptr->member\u function();
。调用
member\u function()
是在析构函数完成后生成的。我的解释不同。标准的哪一部分支持这个答案?@chill请参见
[class.dtor]一节
特别是
类X的析构函数调用X的直接非变量非静态数据成员的析构函数、X的非虚拟直接基类的析构函数,如果X是最派生的类([class.base.init]),它的析构函数调用X的虚拟基类的析构函数。
。我认为该标准实际上没有定义“完成执行”的含义,因此我们只能进行人工解释。如果析构函数调用子对象析构函数,那么我的解释是它还没有完成执行。事实上,谢谢,我刚刚找到了同样的结果,“在执行析构函数体[…]之后,类X的析构函数调用…”即,它仍然在执行,因为它调用东西。