C++ 中类静态变量的生命周期是多少?
-
21-08-2019 - |
题
如果我有一个名为 Test :: 的类
class Test
{
static std::vector<int> staticVector;
};
什么时候 静态向量 被建造以及什么时候被摧毁?
是通过 Test 类的第一个对象的实例化,还是像常规静态变量一样?
澄清一下,在阅读《编程语言概念》(Sebesta Ch-5.4.3.1)后,我想到了这个问题,它说::
请注意,当 静止的 修饰符出现在C ++,Java和C#类定义中变量的声明中,它与变量的寿命无关。在这种情况下,这意味着变量是类变量,而不是实例变量。保留单词的多重用法可能会使学习语言的人感到困惑。
你明白了吗?:(
解决方案
酷似常规静态的(全局)变量。
其他提示
我也想写一些关于初始化的文本,稍后我可以链接到它。
首先列出可能性。
- 命名空间 静止的
- 班级 静止的
- 当地的 静止的
命名空间静态
- 有两种初始化方法。 静止的 (打算在编译时发生)和 动态的 (打算在运行时发生)初始化。
- 静止的 初始化 发生在之前 任何动态初始化,忽略翻译单元关系。
- 动态的 初始化在翻译单元中是有顺序的,而静态初始化没有特定的顺序。同一翻译单元的名称空间范围的对象按照其定义出现的顺序动态初始化。
- 使用常量表达式初始化的 POD 类型对象是静态初始化的。任何对象的动态初始化都可以依赖它们的值,而不考虑翻译单元关系。
- 如果初始化抛出异常,
std::terminate
叫做。
例子:
以下程序打印 A(1) A(2)
struct A {
A(int n) { std::printf(" A(%d) ", n); }
};
A a(1);
A b(2);
以下基于同一个类,打印 A(2) A(1)
extern A a;
A b(2);
A a(1);
假设有一个翻译单元 msg
定义如下
char const *msg = "abc";
然后打印出以下内容 abc
. 。注意 p
接收动态初始化。但因为静态初始化(char const*
是 POD 类型,并且 "abc"
是一个地址常量表达式) msg
在那之前发生,这很好,并且 msg
保证正确初始化。
extern const char *msg;
struct P { P() { std::printf("%s", msg); } };
P p;
- 动态的 不惜一切代价,对象的初始化不需要在 main 之前发生。不过,初始化必须在首次使用其翻译单元的对象或函数之前进行。这对于动态可加载库很重要。
静态类
- 行为类似于命名空间静态。
- 还有一个关于是否允许编译器在首次使用其翻译单元的函数或对象时(在 main 之后)初始化类静态的错误报告。标准中的措辞目前仅允许命名空间范围对象这样做 - 但似乎它也打算允许类范围对象这样做。读 命名空间范围的对象.
- 对于模板成员的类静态,规则是它们仅在使用时才被初始化。不使用它们将不会产生初始化。请注意,无论如何,初始化都会像上面解释的那样发生。初始化不会因为它是模板的成员而被延迟。
本地静态
- 对于局部静态,会发生特殊规则。
- 使用常量表达式初始化的 POD 类型对象在进入定义它们的块之前进行初始化。
- 其他本地静态对象在控制第一次通过它们的定义时被初始化。当抛出异常时,初始化不被认为完成。下次将再次尝试初始化。
例子:以下程序打印 0 1
:
struct C {
C(int n) {
if(n == 0)
throw n;
this->n = n;
}
int n;
};
int f(int n) {
static C c(n);
return c.n;
}
int main() {
try {
f(0);
} catch(int n) {
std::cout << n << " ";
}
f(1); // initializes successfully
std::cout << f(2);
}
在上述所有情况下,在某些有限的情况下,对于一些不需要静态初始化的对象,编译器可以静态初始化它,而不是动态初始化它。这是一个棘手的问题,请参阅 这个答案 以获得更详细的示例。
另请注意,销毁顺序是对象构造完成的确切顺序。这是很常见的情况,在 C++ 中的各种情况下都会发生,包括破坏临时变量。
它能够在全局变量得到的构造相同的时间建造,并与全局破坏一起为好。
简单地说:结果 全局变量被构造时的静态成员变量构成。全局变量的施工顺序没有限定,但输入的主功能是之前它发生。
当全局变量被破坏销毁发生。
全局变量是在它们被构造的相反的顺序被破坏;离开主功能后。
的问候,结果 Ovanes
P.S:我建议看看C ++ - 标准,这解释了(定义)如何和何时全局或静态成员变量被构造或破坏
P.P.S:您的代码只声明静态成员变量,但不对其进行初始化。要初始化它,你必须在编译单元的一个写:
的std ::向量测试:: staticVector;结果 或点击 的std ::向量测试:: staticVector =标准::向量(/ *这里构造函数PARAMS * /);
一些特定的 VC++ 信息(如果您正在使用这些信息):
- 静态类变量构造与其他静态/全局变量同时发生。
- 在 Windows 中,CRT 启动函数负责此构造。这是您编译的大多数程序的实际入口点(它是调用 Main/Winmain 函数的函数)。此外,它还负责初始化整个C运行时支持(例如您需要它来使用malloc)。
- 构造的顺序是未定义的,但是当使用microsoft VC编译器时,基本类型的构造顺序是可以的,例如这样写是合法且安全的
静态.h:...MyClass 声明...静态常量 int a;静态 int b;静态 int ar[];} statics.cpp:
const int MyClass::a = 2;
int MyClass::b = a+3;
int MyClass::ar[a] = {1,2}
一个静态类成员变量意味着即使有同一个类的多个对象,该变量将是类的所有对象的相同。
因此,我会说,当第一对象被实例化,并破坏时最后一个对象desctructed其构造。