如果我有一堂课:
对象.h
class Object
{
public:
static int number;
};
对象.cpp
int Object::number = 5;
的范围是否Object::number
保证比创建的任何实例的范围更持久Object
?即使它在另一个源文件中全局声明?
如果我有一堂课:
对象.h
class Object
{
public:
static int number;
};
对象.cpp
int Object::number = 5;
的范围是否Object::number
保证比创建的任何实例的范围更持久Object
?即使它在另一个源文件中全局声明?
是的,它具有“静态存储持续时间”,这意味着它“一直”存在[如果它有一个非标准构造函数,则在“main”开始之前调用构造函数——这对于大多数意图和目的来说应该足够了]
有点,但只是因为int
是一个特例。例如,假设您输入Object.cpp
:
Object o = {};
int Object::number = 5;
然后对象o
具有静态存储持续时间,就像这样Object::number
做一样。它名义上是之前创建的,之后number
会被销毁,但是由于它们都是 POD,因此这种销毁实际上没有任何效果。
但是,如果number
并且o
有非平凡的析构函数, thennumber
将在o
. number
就破坏顺序而言,它是类的静态成员这一事实o
并没有给它任何特殊处理。
如果o
在另一个源文件中处于关闭状态,则未指定构造顺序,并且破坏顺序是构造的相反顺序(同样,如果它们具有非平凡的析构函数——int
这是一种特殊情况,因为它没有)。
是的,有两个原因:
总之,这意味着它在静态初始化阶段被初始化,在任何用户定义的代码(包括静态对象的构造函数)运行之前。因此,在任何代码可以访问它之前,它保证存在并被初始化。
如果它具有构造函数或非常量初始化器,那么它将在动态初始化期间与所有其他此类对象一起初始化。在这种情况下,另一个静态对象的构造函数或初始化程序可能会在初始化之前访问该对象。该问题有时被称为“静态初始化顺序惨败”。
考虑这个 g++ 程序:
#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()
所以,不,一般来说,“[成员]的[生命周期]”不是“保证比所创建的任何对象实例的[生命周期]更长?”
标准保证具有静态存储持续时间的对象在程序的整个持续时间内都存在。
C++03, 3.7.1 静态存储时长§1:
所有既不具有动态存储持续时间也不是本地对象的对象具有静态存储持续时间。这些对象的存储将持续到程序的持续时间
在您的示例中,§4也是相关的:
static
应用于类定义中的类数据成员的关键字赋予数据成员静态存储持续时间。