静态局部变量

  通常在函数体内定义的局部变量,当程序运行到该语句时会给该局部变量分配栈内存。但随着程序退出函数体,系统就会收回栈内存,局部变量也相应失效。

  在局部变量前加上关键字"static",就被定义成为一个静态局部变量。静态局部变量保存在全局数据区,而不是保存在栈中,每次的值保持到下一次调用,直到下次赋新值。

  静态局部变量的用途有许多:可以使用它确定某函数是否被调用过。使用它保留多次调用的值。

  如果是通过定义一个全局变量来实现,那变量已经不再属于函数本身了,不再仅受函数的控制,给程序的维护带来不便。

代码示例:

#include <iostream>
using namespace std;
void func();
int main()
{
    func();
    func();
    func();
}
void func()
{
    static int  n=10;
    cout<<n<<endl;
    ++n;
}

输出:

10
11
12

  程序中静态局部变量n仅在第一次调用时被初始化,第二次进入该函数时,不再进行初始化,这时它的值是第一次调用后的结果值11。

静态局部变区别:

  1. 静态局部变量在静态存储区内分配存储单元,在程序整个运行期间都不释放。而普通局部变量属于动态存储类别,存储在动态存储区空间,函数调用结束后即释放;
  2. 静态局部变量只初始化一次,以后每次调用函数时保留上次函数调用结束时的值。而自动变量每调用一次函数重新执行一次赋值语句;
  3. 静态局部变量一般在声明处初始化,如果没有显式初始化,会被程序自动初始化为0(对数值型变量)或空字符(对字符型变量)。而对自动变量来说,如果不赋初值,则它的值是一个不确定的值。这是由于每次函数调用结束后存储单元已释放,下次调用时又重新另分配存储单元,而所分配的单元中的值是不确定的。
  4. 静态局部变量始终驻留在全局数据区,直到程序运行结束。但其作用域仍为局部作用域,当定义它的函数或语句块结束时,其作用域随之结束。虽然静态局部变量在函数调用结束后仍然存在,但其他函数是不能引用它的。

关于局部静态变量初始化时机:

这里引用我觉得另一个博主写的很好的答案。

  首先,静态局部变量和全局变量一样,数据都存放在全局区域,所以在主程序之前,编译器已经为其分配好了内存,但在C和C++中静态局部变量的初始化节点又有点不太一样。

  在C中,初始化发生在代码执行之前,编译阶段分配好内存之后,就会进行初始化,所以我们看到在C语言中无法使用变量对静态局部变量进行初始化,在程序运行结束,变量所处的全局内存会被全部回收。

  而在C++中,初始化时在执行相关代码时才会进行初始化,主要是由于C++引入对象后,要进行初始化必须执行相应构造函数和析构函数,在构造函数或析构函数中经常会需要进行某些程序中需要进行的特定操作,并非简单地分配内存。所以C++标准定为全局或静态对象是有首次用到时才会进行构造,并通过atexit()来管理。在程序结束,按照构造顺序反方向进行逐个析构。所以在C++中是可以使用变量对静态局部变量进行初始化的。

 

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

  这个问题C和C++的处理方式也是不一样的。C中编译器会直接跳过这一个语句,因为在编译的时候已经对静态局部变量进行过分配空间并初始化,所以代码执行过程中根本不需要再次执行。而在C++中,编译器会在编译器分配内存后,在全局区域(当前静态局部变量的地址)附近同样分配一块空间,进行记录变量是否已经进行过初始化。之所以说附近是根据编译器不同,处理方式不同导致的。

 

C++11

 

posted @ 2020-04-15 11:24  程序虫  阅读(6012)  评论(0编辑  收藏  举报