C++における局所静的変数の呼び出し問題

5408 ワード

問題の背景は、「C++Primer」を学習する際に、「6.1.1ローカルオブジェクト」の「ローカル静的変数」の知識を学び、例:
size_t count_called()
{
    static size_t ctr = 0;
    return++ctr;
}
int main()
{
    for(size_t i=0; i!=10; i++)
        cout<
    return 0;
}
プログラムは1から10の数字を出力します.
質問:
2回目の呼び出しcount_called()関数の場合、
static size_t ctr = 0;
文に「error:redeclaration of...」が発生するかどうかなどの再宣言ミスは?答えは:いいえ.では、なぜこの文を繰り返し実行せず、オブジェクトctrの値を毎回0にリセットするのでしょうか.答えは、2回目に関数を呼び出すと、局所静的変数ctrは再初期化されません.最初の初期化で唯一の初期化を行います静的ストレージでguard変数を設定します(目測では、この変数はブール型であると考えられます).1回目以降に関数を呼び出して文に出会った場合、guard変数の値を判断し、タグが初期化されている場合はオブジェクトを直接使用します.簡単に言えば、ローカル静的変数は1回しか初期化されず、後でその関数を呼び出してオブジェクト値を直接使用し、再初期化されません.
追加:
(1)
静的変数記憶領域の概念については、C/C++スタック、スタック、および静的データ領域の詳細を参照してください.
(2)

c++関数の局所静的変数が2回目にアクセスされたとき具体的に何をしましたか?
」という質問にも回答がありました.
(a)
2.8 Initialization Guard Variables
If a function-scope static variable or a static data member with vague linkage (i.e., a static data member of a class template) is dynamically initialized, then there is an associated guard variable which is used to guarantee that construction occurs only once. The guard variable's name is mangled based on the mangling of the guarded object name. Thus, for function-scope static variables, if multiple instances of the function body are emitted (e.g., due to inlining), each function uses the same guard variable to ensure that the function-scope static is initialized only once. Similarly, if a static data member is instantiated in multiple object files, the initialization code in each object file will use the same guard variable to ensure that the static data member is initialized only once.
The size of the guard variable is 64 bits. The first byte (i.e. the byte at the address of the full variable) shall contain the value 0 prior to initialization of the associated variable, and 1 after initialization is complete. Usage of the other bytes of the guard variable is implementation-defined.
See Section 3.3.2 for the API for references to this guard variable.
によると
3.3.2 One-time Construction API
」ということで、
  if (obj_guard.first_byte == 0) {              //zi  obj_guard 0,         
    if ( __cxa_guard_acquire (&obj_guard) ) {   //zi   ,        
      try {
	... initialize the object ...;
      } catch (...) {
        __cxa_guard_abort (&obj_guard);
        throw;
      }
      ... queue object destructor with __cxa_atexit() ...;
      __cxa_guard_release (&obj_guard);          //zi   
    }
  }
,guard_object 1,“ ”; ,guard_object 0 , ”。

"Returns 1 if the initialization is not yet complete......"、“Sets the first byte of the guard object to a non-zero value. This function extern "C" void __cxa_guard_release ( __int64_t *guard_object ) is called after initialization is complete.....

(b)

“ msvc 。 , , , 。 , , 。”