关于析构函数中对象生命周期的说明 15.7 构建和销毁

问题描述

Another question 引用了 C++ 标准:

3.8/1 "类型 T 的对象的生命周期在以下情况下结束: — 如果 T 是具有非平凡析构函数的类类型 (12.4),则析构函数调用 开始,或者——对象占用的存储被重用或者 发布。”

这似乎意味着不允许从析构函数访问对象的成员。然而,这似乎是错误的,事实更像是 Kerrek SB 的回答中所解释的:

成员对象在构造函数体运行之前就活跃起来,并且它们 一直存活到析构函数结束。因此,您可以 在构造函数和析构函数中引用成员对象。

对象本身直到它自己的构造函数之后才活跃起来 完成,并且在其析构函数开始执行时立即死亡。但 这只是就外部世界而言。构造函数和 析构函数仍然可以引用成员对象。

我想知道在析构函数中是否可以将对象的地址传递给外部类,例如:

struct Person;
struct Organizer
{
     static void removeFromGuestList(const Person& person); // This then accesses Person members
}

struct Person
{
     ~Person() {
      // I'm about to die,I won't make it to the party
      Organizer::removeFromGuestList(*this);
}

};

这对我来说似乎没问题,因为我认为对象的生命周期一直持续到析构函数完成之后,但是上述答案的这一部分让我怀疑:

对象本身直到它自己的构造函数之后才活跃起来 结束,并且在它的析构函数开始执行时它就会死亡。但是 这只是就外部世界而言。构造函数和 析构函数仍然可以引用成员对象。

解决方法

关于在析构函数执行期间 类成员的确切状态,C++ 标准似乎确实有点自相矛盾。

但是,以下摘录 Draft C++ Standard 可能可以让您放心,您对 removeFromGuestList 函数的调用应该是安全的(我添加了粗斜体格式):

15.7 构建和销毁

1 对于具有非平凡构造函数的对象,指的是任何非静态成员或基类 构造函数开始执行之前对象的类导致 未定义的行为。对于具有非平凡析构函数的对象, 引用对象的任何非静态成员或基类之后 析构函数完成执行导致未定义的行为。

尚不清楚(至少对我而言)的是,一旦析构函数开始执行,通过对被销毁对象的引用来引用这些类成员是否有效。也就是说,假设您的 Person 类有一个成员 ObjectType a,在您的 person.a 函数中引用 removeFromGuestList 是否有效?

另一方面,与其将 *this 作为参数传递,不如将每个必需成员作为“不同对象”传递,那么您是安全的;因此,将该函数重新定义为 removeFromGuestList(const ObjectType& a)(带有可能的附加参数)将是完全安全的。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...