static变量在Main函数之前执行

本文探讨了C++语言中静态变量的初始化时机和特性,通过具体实例展示了静态变量可以在类外单独初始化,并且初始化操作发生在main函数之前。同时,分析了一个使用boost库实现单例模式的例子,强调了静态变量在类生命周期中的应用。

一、例1

c/c++语言中,在执行main的入口函数之前,是会首先执行一段代码。

而对于全局变量和static的初始化就是 在main函数之前执行的,例子如下:

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #include <iostrem.h>  
  2.   
  3. #include  <stdio.h>  
  4.   
  5. class static_name  
  6.   
  7. {  
  8.   
  9. public:  
  10.   
  11.     static_name(){};  
  12.   
  13.     static int  static_print();  
  14.   
  15. private:  
  16.   
  17.     static  int  i_static_value;  
  18.   
  19. };  
  20.   
  21. int static_name:static_print()  
  22.   
  23. {  
  24.   
  25.     printf("This is static!!\n");  
  26.   
  27.     return 1;  
  28.   
  29. }  
  30.   
  31. int static_name::i_static_value=static_name::static_print();  
  32.   
  33. int main()  
  34.   
  35. {  
  36.   
  37.     printf("This is main_function()!!\n");  
  38.   
  39.     return 0;  
  40.   
  41. }  



执行结果为:

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. This is static!!  
  2.   
  3. This is main_function()!!  


这就说明:

1.类中static变量是可以不在构造函数中初始化的,可以在类外面单独初始化。

2.static变量初始化执行,是在main入口函数之前就完成的操作。


【转自:http://blog.youkuaiyun.com/zhghost/article/details/8693494】


再看例2:


二、例2

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #include <boost/serialization/singleton.hpp>  
  2. using namespace std;  
  3. using boost::serialization::singleton;  
  4.   
  5. class Point  
  6. {  
  7. public:  
  8.     explicit Point(int a=0, int b=0, int c=0):x(a),y(b),z(c)  
  9.     {  
  10.         cout<<"point ctor"<<endl;  
  11.     }  
  12.     ~Point()  
  13.     {  
  14.         cout<<"point dtor"<<endl;  
  15.     }  
  16.     void Print()const  
  17.     {  
  18.         cout<<"x="<<x<<", y="<<y<<", z="<<z<<endl;  
  19.     }  
  20. private:  
  21.     int x, y, z;  
  22. };  
  23.   
  24. int main ( )  
  25. {  
  26.     cout<<"main() start"<<endl;  
  27.     typedef singleton<Point> origin;  
  28.   
  29.     origin::get_const_instance().Print();  
  30.       
  31.     cout<<"main() finish"<<endl;  
  32.   
  33.     return 0;  
  34. }  

执行结果为:

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. <span style="color:#ff0000;">point ctor</span>  
  2. main() start  
  3. x=0, y=0, z=0  
  4. main() finish  
  5. point dtor  
<think>好的,我现在要回答用户关于C/C++函数static变量初始化时机的问题。首先,我需要回顾一下相关的知识,并结合提供的引用资料来确保回答准确。 用户的问题很明确,想知道函数中的static变量什么时候初始化。根据我之前学过的内容,static变量函数内部有不同的初始化时机,这可能和存储位置、生命周期有关。让我先理清楚基本概念。 首先,引用[2]中提到,静态局部变量函数中定义后,只会初始化一次,并在函数调用结束后保留其值。这说明static变量函数内的生命周期是从第一次执行到程序结束,而不是每次函数调用都重新初始化。那初始化具体是什么时候进行的呢? 引用[5]提到,static变量的初始化可能发生在编译时、加载时或运行时。如果是编译时初始化,可能在程序运行前就已经完成。但如果是需要动态初始化的,比如构造对象,那可能在第一次进入函数时初始化。这里可能存在线程安全问题,如果初始化发生在运行时且多线程环境下同时访问该函数,可能会有竞争条件。 再看引用[1]中的例子,函数Foo中的static int a=3;这里a的初始化是在第一次调用Foo时进行的吗?还是更早?根据C++标准,局部静态变量的初始化是在控制流首次到达其声明时进行的,且只会进行一次。这称为“延迟初始化”或“首次使用时初始化”。 但如果是编译时常量的初始化,比如static int a=3,可能编译器会优化为在程序启动时初始化,但标准规定的是在第一次执行到的时候。比如,如果有static int a = func(); 这里func()是在运行时调用的,所以必须延迟到首次调用函数执行。 然后,引用[5]中还提到,如果初始化是在运行时,可能存在线程安全问题。比如,在C++11之前,多个线程首次同时调用该函数,可能导致多次初始化,但C++11之后标准规定静态局部变量的初始化是线程安全的,会加锁保证只初始化一次。 现在需要将这些信息整合,分点回答用户的问题。应该包括初始化时机(第一次执行到声明处)、线程安全情况、与全局静态变量的区别等。 可能还需要提到,函数内的static变量和类中的静态成员变量的区别,例如类中的静态成员需要在类外单独初始化,如引用[3]中的例子。而函数内的static变量初始化是在函数内部声明处。 另外,引用[4]提到全局变量未初始化的默认值,但函数内的static变量如果没有显式初始化,会被初始化为零(对于内置类型),因为静态存储期的变量默认初始化为零,而自动变量则不会。所以函数内的static变量即使不显式初始化,也会在首次初始化时设置为0。 总结起来,回答的结构应该是: 1. 初始化时机:首次执行到声明处,且仅一次。 2. 线程安全:C++11后的保证。 3. 默认初始化规则:内置类型初始化为0。 4. 与全局变量、类静态成员的区别。 5. 可能的优化情况(编译时常量是否提前初始化)。 然后根据用户提供的引用资料,确认是否有需要补充的地方。例如引用[1]中的示例代码,static int a=3是在第一次调用Foo时初始化的,并且之后每次调用保留值。引用[5]提到运行时初始化的线程安全问题,而C++11后的处理方式。需要指出这些点。 可能生成的相关问题包括:函数static变量和全局static变量的区别?C++如何保证静态局部变量的线程安全?静态变量未初始化时的默认值是什么? 需要确保回答正确,并引用相关的引用资料中的内容,比如引用[2]说明静态局部变量的特性,引用[5]关于初始化时机和线程安全的内容。同时注意用户提供的示例代码中的情况,如a的初始化和自增。 最后,用中文清晰、分点回答,并按照用户的要求在末尾添加相关问题。</think>### C/C++函数static变量的初始化时机 在C/C++中,函数内部的**静态局部变量static变量)** 的初始化时机遵循以下规则: --- #### 1. **初始化时机:首次执行到声明处** 静态局部变量**仅在第一次执行到其声明语句时初始化一次**,后续调用直接使用已初始化的值[^2][^5]。 例如以下代码: ```cpp void Foo() { static int a = 3; // 初始化仅执行一次 std::cout << a; a++; } ``` - 第一次调用`Foo()`时,`a`被初始化为3,输出3后变为4。 - 第二次调用时,跳过初始化,直接输出4,再变为5,以此类推。 --- #### 2. **线程安全性(C++11及以后)** - **C++11之前**:若多个线程首次同时调用含静态局部变量函数,可能导致重复初始化或竞态条件[^5]。 - **C++11及以后**:标准规定静态局部变量的初始化是线程安全的,编译器会隐式加锁确保仅初始化一次[^5]。 --- #### 3. **默认初始化规则** - 若未显式初始化,**内置类型(如`int`、`float`)** 的静态局部变量会被默认初始化为0[^4]。 - **类类型** 的静态局部变量会调用默认构造函数初始化(若无默认构造函数需显式初始化)。 --- #### 4. **与全局变量、类静态成员的区别** | 类型 | 初始化时机 | 作用域 | |------------------|----------------------------|---------------------| | 函数static变量 | 首次执行到声明语句时 | 函数内部 | | 全局static变量 | 程序启动时(main函数前) | 文件内可见 | | 类静态成员变量 | 需在类外单独初始化(见示例)| 类作用域 | 类静态成员变量初始化示例[^3]: ```cpp class MyClass { public: static int count; // 声明 }; int MyClass::count = 0; // 类外初始化 ``` --- ### 关键总结 - **唯一性**:静态局部变量在程序生命周期内仅一份实例。 - **延迟初始化**:首次调用函数时才初始化,适合资源延迟加载。 - **线程安全**:C++11后无需手动处理多线程初始化问题[^5]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值