C++從靜態對象的初始化順序理解static關鍵字


問題

首先考慮一個全局變量的初始化順序問題

在頭文件1中:

extern int b;
int a = b + 1;

 

在頭文件2中:

extern int a;
int b = a + 1;

源文件中包含了頭文件1和頭文件2,這種情況下a和b可能的值是什么呢?

雖然在開發過程一般不會出現上述這種情況,但是這核心的是一個全局變量初始化順序的問題,這個問題在團隊開發過程可能會碰到。

可以使用static的特性來解決此問題,static關鍵字作用一般有以下幾點:

1. 靜態全局變量,變量在該翻譯單元是可見的,但是在其他翻譯單元中是不可見的(翻譯單元暫時理解為源文件,后文解析)。如下:

//源文件1中
static int n;
//源文件2中
extern int n;//這里編譯無錯,但鏈接出錯,因為源文件1中的n是外部不可見的

2. 靜態局部變量,變量雖然是一個局部變量,但是它在全局變量區分配內存,該變量在局部可見,並且只初始化一次。

3. 靜態函數,和靜態全局變量一樣,該翻譯單元可見,外部不可見。

4. 類中靜態成員變量,變量需要在類外部聲明,所有類的對象共用一個靜態成員變量。

5. 類中靜態成員函數。

解決方式

Initializer.h中:

#ifndef INITIALIZER_H
#define INITIALIZER_H
#include <iostream>
extern int x;
extern int y;

class Initializer
{
    static int initCount;
public:
    Initializer() 
    {
        std::cout << "Initializer()" << std::endl;
        if (initCount++ == 0)
        {
            std::cout << "performint initialization"
                << std::endl;
            x = 100;
            y = 200;
        }
    }
    ~Initializer()
    {
        std::cout << "~Initializer()" << std::endl;
        if (--initCount == 0)
        {
            std::cout << "performint cleanup"
                << std::endl;
        }
    }
    void testFun()
    {
        std::cout << "testFun"<< initCount << std::endl;
    }
private:

};
static Initializer init;
#endif

 

Initializer.cpp

#include "Initializer.h"

int x;
int y;
int Initializer::initCount;

 

其他cpp文件只需要包含頭文件即可自動解決x和y的初始化順序問題。

#include "Initializer.h"

在Initializer.h定義了一個靜態全局變量,這個變量在一個翻譯單元是內部可見的,所以Initializer.cpp和所有包含Initializer.h的源文件中都會又有一個init變量,這個變量雖然名稱相同,但是每個翻譯單元的init變量地址是不同的。不理解的話可以考慮下面代碼的輸出:

header.h中:

static int nCount = 1;

 

fun.cpp中:

#include "header.h"
#include <iostream>
void fun()
{
    std::cout << "enter fun:" << &nCount << "\t" << nCount << std::endl;
    nCount++;
    std::cout << "leave fun:" << &nCount << "\t" << nCount << std::endl;
}

main.cpp中:

#include "header.h"
#include <iostream>
extern void fun();

int main()
{
    std::cout << "enter main:" << &nCount << "\t" << nCount << std::endl;
    fun();
    std::cout << "leave main:" << &nCount << "\t" << nCount << std::endl;
    return 0;
}

header.h中定義了一個靜態全局變量,fun.cpp是一個翻譯單元,編譯fun.cpp時,nCount是一個內部可見(fun.cpp內可見)的全局變量。編譯main.cpp時,nCount是一個內部可見(main.cpp內可見)的全局變量,這兩個變量雖然變量名是一樣的,但是地址是完全不同的。

輸出如下:

image


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM