最终,没有区别。忽略(暂时)静态成员函数,static
意味着它的含义——但我们在不同的条件下看到它的不同部分,因为它的某些含义也可以在没有关键字的情况下发生。
当您使用static
关键字时,被定义的对象始终具有:
- 静态生命周期——它存在于程序的整个生命周期。
- 本地可见性——名称在其声明的范围之外不可见。
无论是在块内部还是外部定义的静态变量,这两者都是正确的。默认情况下会发生其中的一部分,即使您不使用static
关键字,但如果您使用关键字,您总是会得到两者。
static
成员函数是类似的,但由于它们是函数,它们并不完全具有生命周期——所有函数都有静态生命周期。静态成员函数具有局部可见性(即,它的名称仅在其类中可见)和类似于“静态生命周期”的东西——该函数不绑定到类的实例。
对于那些关心初始化块级静态变量的具体时间的人,血腥细节如下(第 6.7/4 节):
具有静态存储持续时间 (3.7.1) 或线程存储持续时间 (3.7.2) 的所有块范围变量的零初始化 (8.5) 在任何其他初始化发生之前执行。如果适用,具有静态存储持续时间的块范围实体的常量初始化(3.6.2)在其块首次进入之前执行。
允许实现在与允许实现在命名空间范围(3.6.2)中静态初始化具有静态或线程存储持续时间的变量相同的条件下,对具有静态或线程存储持续时间的其他块范围变量执行早期初始化。否则,此类变量在控件第一次通过其声明时被初始化;这样的变量在其初始化完成时被认为已初始化。
因此,该变量将在程序启动的早期初始化为零。然后,如果已指定其他初始化,则不会迟于执行通过初始化时发生(但可能会更早发生)。但是,请注意常量初始化和其他初始化之间的区别。例如,考虑这样的事情:
int g() { return 2; }
int f() {
goto bypass;
static int x = 1;
static int y = g();
bypass:
std::cout << x << "\n" << y;
}
在这里,x
是常量初始化,但y
不是。由于x
是常量初始化,它在进入块时被初始化,所以当我们打印出它的值时,我们应该得到1
. y
但是,它不是常量初始化的,并且 goto 意味着执行永远不会通过其初始化 - 因此,它将保留0
在任何其他初始化发生之前它被初始化的那个,因此(使用正常运行的编译器)输出将是:
1
0