当前位置: 代码迷 >> 综合 >> C++全局变量执行顺序(#pragma init_seg)
  详细解决方案

C++全局变量执行顺序(#pragma init_seg)

热度:75   发布时间:2023-10-31 05:48:58.0

在C++中的全局变量的构造总是优先于Main之前(应该说程序的执行体)

1)对于同一个文件(CPP)来说:

全局变量的构造顺序按照全局变量的声明来构造。

//同一个cpp中
C_C g_C;
C_A g_A;
C_B g_B;

构造函数的执行顺序为:C_C(), C_A(), C_B(), 不管是在什么编译器上都是按照这样的顺序执行的,在C++标准中,处于同一编译单元(cpp)的全局对象按其声明次序初始化并倒序析构

2)对于不同文件来说:

全局变量的构造顺序是不确定的。

//C.cpp
C_C g_objC;
//B.cpp
C_B g_objB;
//A.cpp
C_A g_objA;
//它们构造函数执行的顺序是任意的

在C++标准中没有说处于不同编译单元的全局对象的初始化顺序。

3)如何保证一个全局变量的构造函数的调用优先于所有的其他构造函数,而不管这些变量是否在同一个文件中.

利用预编译指令:#pragma init_seg({ compiler | lib | user | "section-name" [, func-name]} )

#pragma init_seg(compiler)
#pragma init_seg(lib)
#pragma init_seg(user)
#pragma init_seg("user_defined_segment_name")

init_seg 预处理器指令: 编译器、 库、 用户,和 user_defined_segment_name, 前三个指令的初始化优先次序依次降低,但都先于普通的全局变量构造,如cout就是使用compiler级别构造的。

注:一个源文件只能出现一次init_seg 指令.

pragma init_seg(compiler)是保留给微软C/C++ 运行库使用的,我们不应该使用它!

在我们自己的代码里,如果希望一些对象先于其他对象初始化,我们可以使用 #pragma init_seg(lib) 指令.

(一) 对于同一个文件来说,我们把全局变量的构造函数的执行顺序强制更改.

//main.cpp
C_C g_C;
C_A g_A;
C_B g_B;

对以上的代码,不管在什么环境下执行,构造函数执行顺序都是固定的,即先执行C_C(), 接着是C_A(), 最后是C_B(), 那么如果我们想更该为先执行C_A(), C_B(), 最后才执行C_C(),那我们这样更改:

//A.pp
C_A::C_A()
{	
printf("C_A Constructor.\n");
}
//B.pp
C_B::C_B()
{	
printf("C_B Constructor.\n");
}
//C.pp
C_C::C_C()
{	
printf("C_C Constructor.\n");
}
C_C g_C;
#pragma init_seg(lib)
C_A g_A;
C_B g_B;
int main(int argc, char* argv[])
{
printf("Hello World!\n");
return 0;
}

执行结果如:

C_A Constructor.
C_B Constructor.
C_C Constructor.
Hello World!

(二)对于不同文件来说,我们把全局变量的构造函数的执行顺序强制更改.

如:以下代码文件:

//A.pp
C_A g_objA;
C_A::C_A()
{	
printf("C_A Constructor.\n");
}
//B.pp
C_B g_objB;
C_B::C_B()
{	
printf("C_B Constructor.\n");
}
//C.pp
C_C g_objC;
C_C::C_C()
{	
printf("C_C Constructor.\n");
}

如果由于某种需求,我要先构造C_C,接着C_B和C_A任意一个,那我们如何做到?当然我们还是要依靠Init_Seg预编译指令.

代码如下:

//A.pp
C_A g_objA;
C_A::C_A()
{	
printf("C_A Constructor.\n");
}
//B.pp
C_B g_objB;
C_B::C_B()
{	
printf("C_B Constructor.\n");
}
//C.pp
#pragma init_seg(lib)
C_C g_objC;
C_C::C_C()
{	
printf("C_C Constructor.\n");
}
//main.cpp
#include "A.h"
#include "B.h"
#include "C.h"
int main(int argc, char* argv[])
{
printf("Hello World!\n");
return 0;
}

执行结果如下:

C_C Constructor.
C_B Constructor.
C_A Constructor.
Hello World!

另外:在测试的一系列过程中,发现在#pragma init_seg(user)下定义的全局变量并没有在其他的全局变量之前构造。