静态类数据成员的范围

时间:2013-03-01 17:35:10

标签: c++ class static global-variables

如果我有课:

Object.h

class Object
{
public:
    static int number;
};

Object.cpp

int Object::number = 5;

Object::number的范围是否保证超出了创建的Object实例的范围?即使它在另一个源文件中全局声明了吗?

5 个答案:

答案 0 :(得分:5)

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

答案 1 :(得分:4)

排序,但只是因为int是特例。例如,假设您在Object.cpp中写道:

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

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

如果numbero有非平凡的析构函数,那么number会在o之前被销毁。 numbero类的静态成员这一事实并未就破坏顺序给予任何特殊处理。

如果o在另一个源文件中关闭,则构造顺序未指定,并且销毁顺序与构造的顺序相反(同样,如果它们具有非平凡的析构函数,则为{ - 1}}是一个特例,因为它没有。)

答案 2 :(得分:3)

是的,有两个原因:

  • 它具有静态存储持续时间,因此其存储持续程序的生命周期
  • 它有一个没有构造函数的类型,用常量表达式初始化。

这意味着它在静态初始化阶段初始化,在运行任何用户定义的代码(包括静态对象的构造函数)之前。因此,在任何代码可以访问它之前,它保证存在并被初始化。

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

答案 3 :(得分:2)

考虑一下这个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()

所以,不,一般而言,“[成员]的[生命周期]”不是“保证会比创建的任何Object实例的[生命周期]更久?”

答案 4 :(得分:1)

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

C ++ 03, 3.7.1静态存储持续时间§1

  

既没有动态存储持续时间也没有本地的所有对象都有静态存储持续时间。这些对象的存储应持续程序的持续时间

在您的示例§4中也是相关的:

  

应用于类定义中的类数据成员的关键字static为数据成员提供静态存储持续时间。