C++从静态对象的初始化顺序理解static关键字

本文探讨了全局变量初始化顺序的问题,并提出了一种利用静态全局变量特性解决该问题的方法。通过具体的代码示例,展示了如何确保不同头文件中互相依赖的全局变量能够正确初始化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题

首先考虑一个全局变量的初始化顺序问题

在头文件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

转载于:https://www.cnblogs.com/Reyzal/p/7230169.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值