全局变量,static变量初始化时间

原文 https://www.cnblogs.com/novice-dxx/p/7094690.html

本次上传主要是关于静态局部变量的初始化问题。

首先,静态局部变量和全局变量一样,数据都存放在全局区域,所以在主程序之前,编译器已经为其分配好了内存,但在C和C++中静态局部变量的初始化节点又有点不太一样在C中,初始化发生在代码执行之前,编译阶段分配好内存之后,就会进行初始化,所以我们看到在C语言中无法使用变量对静态局部变量进行初始化,在程序运行结束,变量所处的全局内存会被全部回收。而在C++中,初始化时在执行相关代码时才会进行初始化,主要是由于C++引入对象后,要进行初始化必须执行相应构造函数和析构函数,在构造函数或析构函数中经常会需要进行某些程序中需要进行的特定操作,并非简单地分配内存。所以C++标准定为全局或静态对象是有首次用到时才会进行构造,并通过atexit()来管理。在程序结束,按照构造顺序反方向进行逐个析构。所以在C++中是可以使用变量对静态局部变量进行初始化的
全局变量、文件域的静态变量和类的静态成员变量在main执行之前的静态初始化过程中分配内存并初始化;局部静态变量(一般为函数内的静态变量)在第一次使用时分配内存并初始化。这里的变量包含内置数据类型和自定义类型的对象。
根据 C++ 标准,全局变量的初始化要在 main 函数执行前完成,常识无疑,但是这个说法有点含糊,main 函数执行前到底具体是什么时候呢?是编译时还是运行时?答案是既有编译时,也可能会有运行时(seriously), 从语言的层面来说,全局变量的初始化可以划分为以下两个阶段(c++11 N3690 3.6.2):

static initialization: 静态初始化指的是用常量来对变量进行初始化,主要包括 zero initialization 和 const initialization,静态初始化在程序加载的过程中完成,对简单类型(内建类型,POD等)来说,从具体实现上看,zero initialization 的变量会被保存在 bss 段,const initialization 的变量则放在 data 段内,程序加载即可完成初始化,这和 c 语言里的全局变量初始化基本是一致的。

dynamic initialization:动态初始化主要是指需要经过函数调用才能完成的初始化,比如说:int a = foo(),或者是复杂类型(类)的初始化(需要调用构造函数)等。这些变量的初始化会在 main 函数执行前由运行时调用相应的代码从而得以进行(函数内的 static 变量除外)。

在这里插入图片描述

后面再来谈谈另一个问题,假如我们在一个循环中,定义了一个静态局部变量并进行初始化,循环过程中**,编译器怎么知道当前的静态局部变量已经初始化过了呢?**

这个问题C和C++的处理方式也是不一样的。C中编译器会直接跳过这一个语句,因为在编译的时候已经对静态局部变量进行过分配空间并初始化,所以代码执行过程中根本不需要再次执行而在C++中,编译器会在编译器分配内存后,在全局区域(当前静态局部变量的地址)附近同样分配一块空间,进行记录变量是否已经进行过初始化。之所以说附近是根据编译器不同,处理方式不同导致的。在网上有博客介绍某种编译器(该吧主并没有透露编译器名字),会在当前变量后面的一个字节进行改变,具体上代码:

### C++ 静态全局变量初始化 在C++中,静态全局变量可以在定义时进行初始化。这类变量具有文件作用域或命名空间作用域,在程序启动前由编译器自动完成初始化。 对于基本类型的静态全局变量,可以直接赋初值: ```cpp // 定义并初始化一个整型静态全局变量 int g_nVal = 10; ``` 如果未显式指定初始值,则会根据类型默认初始化为零或其他适当值[^2]。 对于复杂对象类型的静态全局变量,可以通过调用构造函数来初始化: ```cpp class MyClass { public: MyClass(int val): value(val) {} private: int value; }; MyClass myObject(42); // 使用参数化构造函数初始化 ``` 需要注意的是,多个翻译单元中的静态变量初始化顺序是不确定的,这可能导致潜在的风险。为了避免此类问题,可以采用局部`static`变量的方式延迟初始化,这种方式不仅安全而且支持多线程环境下的正确初始化[^3]。 #### 多线程环境下静态全局变量的安全初始化 为了确保在多线程环境中静态全局变量能够被安全地初始化,现代C++标准提供了内置的支持机制。例如,下面的例子展示了如何利用局部静态变量特性实现线程安全的单例模式实例创建: ```cpp Singleton& getSingletonInstance() { static Singleton instance; // 自动处理一次性和线程安全性 return instance; } ``` 此方法通过编译器保障了即使是在并发场景下也能恰当地执行初始化操作,并且只会在第一次访问该函数时发生。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值