我不明白这一点:
3.8/1 “T 类型对象的生命周期在以下情况下结束: — 如果 T 是具有非平凡析构函数 (12.4) 的类类型,则析构函数调用开始,或者 — 对象占用的存储空间被重用或释放。 "
如果生命周期在析构函数开始之前结束,这是否意味着访问析构函数中的成员是未定义的行为?
我也看到了这句话:
12.7 “对于具有非平凡析构函数的对象,在析构函数完成执行后引用对象的任何非静态成员或基类会导致未定义的行为。”
但它并不清楚在析构函数期间允许什么。
我不明白这一点:
3.8/1 “T 类型对象的生命周期在以下情况下结束: — 如果 T 是具有非平凡析构函数 (12.4) 的类类型,则析构函数调用开始,或者 — 对象占用的存储空间被重用或释放。 "
如果生命周期在析构函数开始之前结束,这是否意味着访问析构函数中的成员是未定义的行为?
我也看到了这句话:
12.7 “对于具有非平凡析构函数的对象,在析构函数完成执行后引用对象的任何非静态成员或基类会导致未定义的行为。”
但它并不清楚在析构函数期间允许什么。
如果生命周期在析构函数开始之前结束,这是否意味着访问析构函数中的成员是未定义的行为?
希望不会:
来自 N3242构造和破坏 [class.cdtor] /3
要形成指向对象 obj 的直接非静态成员的指针(或访问其值),obj 的构造应已开始且其销毁不应完成,否则指针值的计算(或访问该成员) value) 导致未定义的行为。
对象的“生命周期”与对象的消费者相关,而不是对象本身。因此,一旦销毁开始,消费类不应尝试访问对象的成员。
不,没有问题:
成员对象在构造函数主体运行之前活跃,并且在析构函数完成之前它们保持活跃。因此,可以在构造函数和析构函数中引用成员对象。
对象本身直到它自己的构造函数完成后才会活跃起来,并且一旦它的析构函数开始执行它就会死掉。但这只是外界所关心的。构造函数和析构函数仍然可以引用成员对象。
“终生”不是这个意思。它是标准中精确定义的术语,具有多种含义,但它可能没有您想象的所有含义。成员在构造和销毁过程中仍然可以使用,外部代码可以调用成员函数等。
诚然,客户端代码与析构函数同时调用成员函数有点奇怪,但并非闻所未闻,当然也不是语言不允许的。特别是,std::condition_variable
显式允许在有未完成的调用时调用析构函数condition_variable::wait()
。它只在析构函数启动后禁止新的调用。wait()