静态类数据成员的作用域

Scope of the static class data member

本文关键字:作用域 数据成员 静态类      更新时间:2023-10-16

如果我有一个class:

Object.h

class Object
{
public:
    static int number;
};

Object.cpp

int Object::number = 5;

Object::number的作用域是否保证比创建的Object实例的作用域更持久?即使它在另一个源文件中全局声明?

是的,它有'静态存储持续时间',这意味着它"一直存在"[如果它有一个非标准构造函数,构造函数在"main"开始之前被调用-这对于大多数意图和目的来说应该足够了]

有点,但只是因为int是一个特殊情况。例如,假设您在Object.cpp中写:

Object o = {};
int Object::number = 5;

对象o具有静态存储持续时间,就像Object::number一样。名义上它是在number之前创建的,之后会被销毁,但由于它们都是POD,这种销毁实际上没有效果。

如果numbero有非平凡析构函数,那么number将在o之前被销毁。事实上,numbero类的静态成员,就销毁顺序而言,并没有给予它任何特殊的处理。

如果o在另一个源文件中关闭,则构造顺序未指定,并且销毁顺序是相反的构造顺序(再次,这是如果它们具有非平凡的析构函数—int是一个特殊情况,因为它没有)。

可以,原因有二:

  • 它具有静态存储持续时间,因此它的存储持续到程序的生命周期
  • 它的类型没有构造函数,用常量表达式初始化。
总之,这意味着在运行任何用户定义代码(包括静态对象的构造函数)之前,在静态初始化阶段初始化它。因此,在任何代码可以访问它之前,保证它存在并被初始化。

如果它有构造函数或非常量初始化器,那么它将在动态初始化期间与所有其他此类对象一起初始化。在这种情况下,另一个静态对象的构造函数或初始化器可能会在对象初始化之前访问该对象。这个问题有时被称为"静态初始化顺序惨败"。

考虑这个c++程序:

#include <iostream>
#define X() (std::cout << __PRETTY_FUNCTION__ << "n")
struct M {
 M() { X(); }
 ~M() { X(); }
};  
struct C {
 C() { X(); }
 ~C() { X(); }
 static M m;
};
C c;
M C::m;
int main () { X(); }

在这个程序中,c必须在C::m之前初始化,C::m之后销毁。如果编译这个程序并考虑它的输出,您将看到如下内容:

C::C()
M::M()
int main()
M::~M()
C::~C()

所以,不,一般来说,"[成员]的[生存期]""保证比创建的任何Object实例的[生存期]更长?"

标准保证具有静态存储持续时间的对象在程序的整个持续时间内存在。

c++ 03, 3.7.1静态存储时间§1 :

所有既不具有动态存储时间也不具有本地存储时间的对象都具有静态存储时间。这些对象的存储应在程序运行期间持续

和在你的例子中§4也是相关的:

关键字static应用于类定义中的类数据成员,给出该数据成员的静态存储持续时间。