全局变量、类静态变量及函数局部静态变量的初始化顺序

What is the lifetime of class static variables in C++?

First the list of possibilities.

  • Namespace Static
  • Class Static
  • Local Static

Namespace Static

  • There are two initialization methods. static (intended to happen at compile time) and dynamic (intended to happen at runtime) initialization.
  • Static Initialization happens before any dynamic initialization, disregarding of translation unit relations.
  • Dynamic Initiaization is ordered in a translation unit, while there is no particular order in static initialization. * Objects of namespace scope of the same translation unit are dynamically initialized in the order in which their definition appears.
  • POD type objects that are initialized with constant expressions are statically initialized. Their value can be relied on by any object’s dynamic initialization, disregarding of translation unit relations.
    If the initialization throws an exception, std::terminate is called.
    Examples:

The following program prints A(1) A(2)

struct A { 
  A(int n) { std::printf(" A(%d) ", n); } 
};

A a(1);
A b(2);

And the following, based on the same class, prints A(2) A(1)

extern A a;
A b(2);
A a(1);

Let’s pretend there is a translation unit where msg is defined as the following

char const *msg = "abc";

Then the following prints abc. Note that p receives dynamic initialization. But because the static initialization (char const* is a POD type, and "abc" is an address constant expression) of msg happens before that, this is fine, and msg is guaranteed to be correctly initialized.

extern const char *msg;
struct P { P() { std::printf("%s", msg); } };
P p;
  • Dynamic initialization of an object is not required to happen before main at all costs. The initialization must happen before the first use of an object or function of its translation unit, though. This is important for dynamic loadable libraries.

Class Static

  • Behave like namespace statics.
  • There is a bug-report on whether the compiler is allowed to initialize class statics on the first use of a function or object of its translation unit too (after main). The wording in the Standard currently only allows this for namespace scope objects - but it seems it intends to allow this for class scope objects too. Read Objects of Namespace Scope.
  • For class statics that are member of templates the rule is that they are only initialized if they are ever used. Not using them will not yield to an initialization. Note that in any case, initialization will happen like explained above. Initialization will not be delayed because it’s a member of a template.

Local Static

  • For local statics, special rules happen.
  • POD type objects initialized with constant expression are initialized before their block in which they are defined is entered.
  • Other local static objects are initialized at the first time control passes through their definition. Initialization is not considered to be complete when an exception is thrown. The initialization will be tried again the next time.
    Example: The following program prints 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);  
}

In all the above cases, in certain limited cases, for some objects that are not required to be initialized statically, the compiler can statically initialize it, instead of dynamically initializing it. This is a tricky issue, see this answer for a more detailed example.

Also note that the order of destruction is the exact order of the completion of construction of the objects. This is a common and happens in all sort of situations in C++, including in destructing temporaries.

参考

What is the lifetime of class static variables in C++?

What are POD types in C++?

Why do some const variables referring to some exported const variables get the value 0?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
全局变量局部变量、静态全局变量静态局部变量是在编程中常见的变量型,它们有以下区别: 1. 全局变量: - 全局变量是在程序的任何地方都可以访问的变量,它的作用域是整个程序。 - 全局变量在声明时会被初始化,如果没有显式初始化,则会被默认初始化为0或者空值。 - 全局变量的生命周期从程序开始到程序结束。 2. 局部变量: - 局部变量是在特定代码块或函数内部声明的变量,它的作用域仅限于声明它的代码块或函数。 - 局部变量在声明时不会被自动初始化,需要手动赋初值。 - 局部变量的生命周期从其所在的代码块或函数执行开始到执行结束。 3. 静态全局变量: - 静态全局变量全局变量似,也是在整个程序中都可以访问的变量。 - 静态全局变量只能在声明它的文件内部访问,其他文件无法直接访问。 - 静态全局变量在声明时会被初始化,如果没有显式初始化,则会被默认初始化为0或者空值。 - 静态全局变量的生命周期从程序开始到程序结束。 4. 静态局部变量: - 静态局部变量是在函数内部声明的变量,但与普通局部变量不同,它的生命周期不随函数的调用而结束。 - 静态局部变量只会被初始化一次,在函数第一次被调用时初始化,之后保持其值不变。 - 静态局部变量的作用域仅限于声明它的函数内部。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值