C++中全局变量的初始化全过程

 更新时间:2024年08月21日 10:13:13   作者:vcpro126  
这篇文章主要介绍了C++全局变量的初始化全过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

C++全局变量的初始化过程

全局变量在main()前完成初始化(调用构造函数)

在调用构造函数前,全局变量已分配空间,内存全0

多个全局变量的初始化,按照代码编译的顺序

注意:全局变量被访问前可能它还没有调用构造函数初始化。

如果一个项目中,多个dll都用到一个全局变量在共同的lib中,则每个dll都有一个独立的全局变量(地址不同),每个全局变量会初始化。

如下代码,A里面访问了全局变量g_b, 改变全局变量g_a,g_b的顺序 会导致g_b.b的输出结果不同。

如按照A g_a; B g_b 的顺序定义,编译器会先调用A()时,这时g_b还没有调用B(), g_b.b=0,然后赋值 g_b.b=101;

然后调用B(),g_b.b的值被改成1.

#include <istream>
using namespace std;

class B {
 public:
  int b = 1;
};

extern B g_b;
class A {
 public:
  int a = 0;
  A() {
    g_b.b = 101;
  }
};

#if 0
B g_b;
A g_a;
#else
A g_a;
B g_b;
#endif
int main() {
  printf("g_b=%d\n", g_b); //AB: g_b=1; BA: g_b=101
  return 0;
}

C++全局变量初始化的顺序

虽然一直强调不要用全局变量。但是对于特殊的应用场合,还是有全局变量的使用(如某些多进程、多线程的共享资源),我们希望在首次运行(载入)时,系统能够帮助我们进行一些必要的初始化。

If a program starts a thread (30.3), the subsequent initialization of a variable is unsequenced with respect to the initialization of a variable defined in a different translation unit. Otherwise, the initialization of a variable is indeterminately sequenced with respect to the initialization of a variable defined in a different translation unit. If a program starts a thread, the subsequent unordered initialization of a variable is unsequenced with respect to every other dynamic initialization. Otherwise, the unordered initialization of a variable is indeterminately sequenced with respect to every other dynamic initialization

对不同的源文件中的全局变量,标准C++对全局变量初始化的顺序并没有要求。对于同一个原文件中,全局变量按照定义先后顺序初始化。

对于堆类型的全局变量的创建和构造,可能在一个构造函数中调用另一个未构造的全局变量,通常会检查另一个指针是否有效,并在无效时构造那个对象。这就出现一个问题:

一个指针在构造之前,被初始化。c/c++运行时,仍然会再次构造那个指针(全局变量为空指针)。

这会引发资源泄露,甚至运行时错误。

解决措施。虽然按需创建是一种很好的思路。但是必须符合c/c++运行机制。解决方式就是不使用堆创建对象,而是使用栈内存对象(c++内部大使用致双检查锁的方式保证构造一次)。我们也可以自己实现双检查锁的思路,但是我们使用的锁的创建过程,本身就是需要双检查锁定的,这是自相矛盾的。

参考C++标准具体介绍:(原文:Storage class specifiers - cppreference.com

Variables declared at block scope with the specifier static or thread_local (since C++11) have static or thread (since C++11) storage duration but are initialized the first time control passes through their declaration (unless their initialization is zero- or constant-initialization, which can be performed before the block is first entered). On all further calls, the declaration is skipped.

If the initialization throws an exception, the variable is not considered to be initialized, and initialization will be attempted again the next time control passes through the declaration.

If the initialization recursively enters the block in which the variable is being initialized, the behavior is undefined.

If multiple threads attempt to initialize the same static local variable concurrently, the initialization occurs exactly once (similar behavior can be obtained for arbitrary functions with std::call_once).

Note: usual implementations of this feature use variants of the double-checked locking pattern, which reduces runtime overhead for already-initialized local statics to a single non-atomic boolean comparison.

(since C++11)

The destructor for a block-scope static variable is called at program exit, but only if the initialization took place successfully.

Function-local static objects in all definitions of the same inline function (which may be impli

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • C++实现移动立方体示例讲解

    C++实现移动立方体示例讲解

    这篇文章主要介绍了C++实现移动立方体,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧
    2022-12-12
  • 基于MFC实现类的序列化详解

    基于MFC实现类的序列化详解

    序列化是将程序中的对象以一种二进制格式存储到存储设备中(例如文本/数据库等),以实现“永生”或随意“流动”。本文将为大家详细讲讲如何基于MFC实现类的序列化,需要的可以参考一下
    2022-07-07
  • 一篇文章带你实现C语言中常用库函数的模拟

    一篇文章带你实现C语言中常用库函数的模拟

    这篇文章主要介绍了C语言中常用库函数的模拟,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-09-09
  • C++实现十进制数转为其它进制数

    C++实现十进制数转为其它进制数

    这篇文章主要为大家详细介绍了C++实现十进制数转为其它进制数,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-04-04
  • 使用C语言来画出皮卡丘的教程(附代码)

    使用C语言来画出皮卡丘的教程(附代码)

    在C语言中使用图形库画图需要引入graphics.h库,我们可以通过代码实现画出一个可爱的皮卡丘,将皮卡丘的绘制分为以下部分:耳朵、脸部、眼睛、嘴巴、手臂、腿部、尾巴,下面我们就来学习如何使用C语言编写画皮卡丘的代码
    2024-01-01
  • Qt实现电子时钟

    Qt实现电子时钟

    这篇文章主要为大家详细介绍了Qt实现电子时钟,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-06-06
  • 详细分析C++ 异常处理

    详细分析C++ 异常处理

    这篇文章主要介绍了C++ 异常处理的的相关资料,文中示例代码非常详细,帮助大家更好的理解和学习,感兴趣的朋友可以了解下
    2020-06-06
  • 教你使用Matlab制作图形验证码生成器(app designer)

    教你使用Matlab制作图形验证码生成器(app designer)

    这篇文章主要和大家分享如何利用Matlab制作一款图形验证码生成器,文中的实现步骤讲解详细,感兴趣的小伙伴可以跟随小编动手试一试
    2022-02-02
  • C++实现简易五子棋游戏

    C++实现简易五子棋游戏

    这篇文章主要为大家详细介绍了C++实现简易五子棋游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-07-07
  • Qt实现拖拽功能图文教程(支持拖放文件、拖放操作)

    Qt实现拖拽功能图文教程(支持拖放文件、拖放操作)

    这篇文章主要给大家介绍了关于Qt实现拖拽功能(支持拖放文件、拖放操作)的相关资料,Qt是一款多平台的C++应用程序开发框架,它的独特之处在于可以快速开发出拖放式的开发桌面程序,需要的朋友可以参考下
    2023-11-11

最新评论