全局对象和静态变量之间的销毁顺序是什么?

6

可能是重复问题:
C++中的对象销毁

假设我们有两个类,一个叫做 Array,另一个叫做 MessageOnExit

假设 Array 类有一个名为 counter 的静态数据成员。

以下是这些类:

class Array {
public:
    static int counter;
    Array(){counter++;}
    ~Array(){counter--;}
};

class MessageOnExit {
public:
    ~MessageOnExit(){cout << Array::counter;}
};

以下是使用这些类的“主要”内容:
// static variable definition
int Array::counter;
// global object definition
MessageOnExit message;

void main() {
    Array a1, a2;
    Array a3(a1);
}

第一和第二个声明将把counter更改为2,这是在两次调用Empty/Default构造函数之后发生的。 第三个声明不会更改counter,因为将调用默认复制构造函数。
现在当执行main完成时,在a1、a2和a3被销毁后,静态成员counter的值将为-1,然后将调用析构函数,打印出这个值(-1)。
我的问题是,当调用message析构函数时,我们如何知道静态成员counter仍然存在并可用。
另外,如果我改变静态/全局对象/变量的定义顺序,即先定义message,那么该值仍为-1
总之,无论我做了什么更改,当程序终止时,消息析构函数都能成功访问静态成员变量counter,我不明白为什么会这样。据我所知,如果全局对象message首先被定义,那么它的析构函数将最后被调用,因此counter值将对其析构函数不可用。
提前感谢! Guy

看一下这个这个,以及这个 - PaperBirdMaster
在对象被销毁后继续使用它是一个未经诊断的错误,这是一种未定义的行为,所以任何事情都可能发生 - 代码可能在某一天看起来正常工作,但在下一天却出现问题。 - Chris Dodd
我删除了所有粗体文本,因为它会强调不应该被强调的部分。我要么将其删除,要么改成代码引用。如果您认为确实需要,在某些地方可以添加粗体。 - Mark B
重新打开这个问题。这里的重点是,具有平凡析构函数的静态对象永远不会被销毁;请参考aschepler的答案。其他问题的答案中没有清楚地说明这一点。 - Johan Råde
1个回答

7

标准第3.8节规定:

类型为T的对象的生命周期在以下情况下结束:

  • 如果T是具有非平凡析构函数(12.4)的类类型,则析构函数调用开始,或者

  • 对象占用的存储被重用或释放。

现在int不是类类型,并且由于Array::counter具有静态存储期,因此其存储永远不会被释放。因此,Array::counter的生命周期永远不会结束,您可以从任何想要的析构函数中安全地访问它!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接