您的当前位置:首页正文

c++ 局部静态变量(Local Static Objects)

2024-11-07 来源:个人技术集锦

一、C++变量的作用域[1]

 变量可以分为:全局变量、静态全局变量、静态局部变量和局部变量
        按存储区域分,全局变量、静态全局变量和静态局部变量都存放在内存的静态存储区域,局部变量存放在内存的栈区。
        按作用域分,全局变量在整个工程文件内都有效;静态全局变量只在定义它的文件内有效;静态局部变量只在定义它的函数内有效,只是程序仅分配一次内存,函数返回后,该变量不会消失;局部变量在定义它的函数内有效,但是函数返回后失效。
        全局变量和静态变量如果没有手工初始化,则由编译器初始化为0。局部变量的值不可知。当编译一个C++程序时,计算机的内存被分成了4个区域,一个包括程 序的代码,一个包括所有的全局变量,一个是堆栈,还有一个是堆(heap),我们称堆是自由的内存区域,我们可以通过new和delete把对象放在这个 区域。你可以在任何地方分配和释放自由存储区。

局部静态变量

在局部变量之前加上关键字static,局部变量就被定义成为一个局部静态变量。

1)内存中的位置:静态存储区

2)初始化:未经初始化的全局静态变量会被程序自动初始化为0(自动对象的值是任意的,除非他被显示初始化)

3)作用域:作用域仍为局部作用域,当定义它的函数或者语句块结束的时候,作用域随之结束。

[注]当static用来修饰局部变量的时候,它就改变了局部变量的存储位置,从原来的栈中存放改为静态存储区。但是局部静态变量在离开作用域之后,并没有被销毁,而是仍然驻留在内存当中,直到程序结束,只不过我们不能再对他进行访问。

全局静态变量

   在全局变量之前加上关键字static,全局变量就被定义成为一个全局静态变量。

   1)内存中的位置:静态存储区(静态存储区在整个程序运行期间都存在)

   2)初始化:未经初始化的全局静态变量会被程序自动初始化为0(自动对象的值是任意的,除非他被显示初始化)

   3)作用域:全局静态变量在声明他的文件之外是不可见的。准确地讲从定义之处开始到文件结尾。

[注]当static用来修饰全局变量的时候,它就改变了全局变量的作用域(在声明他的文件之外是不可见的),但是没有改变它的存放位置,还是在静态存储区中。

静态函数

在函数的返回类型前加上关键字static,函数就被定义成为静态函数。

函数的定义和声明默认情况下是extern的,但静态函数只是在声明他的文件当中可见,不能被其他文件所用。

静态数据成员

   1) 内存中的位置:静态存储区

   2) 初始化和定义:

       <1> 静态数据成员定义时要分配空间,所以不能在类声明中定义。

       <2> 静态数据成员在程序中只能提供一个定义,所以静态数据成员的初始化不能在类的头文件中。

   3) 访问:

       <1> 类对象名.静态数据成员

       <2> 类类型名::静态数据成员

   4) 说明:

       a.static数据成员和普通数据成员一样遵public, protected, private 访问规则。

       b.对于非静态数据成员,每个类对象都有自己的拷贝。静态数据成员被当作类的全局对象,无论这个类的对象被定义了多少个,静态数据成员在程序中也只有一份拷贝,由该类类型的所有对象共享访问。

   5) 同全局对象相比,使用静态数据成员有两个优势:

       <1> 静态数据成员没有进入程序的全局名字空间,因此不存在与程序中其他全局名字冲突的可能性。

       <2> 可以实现信息隐藏。静态成员可以是private成员,而全局对象不能。

   6 ) 静态数据成员的“唯一性”本质(独立于类的任何对象而存在的唯一实例),使他能够以独特的方式被使用,这些方式对于非static数据成员来说是非法的。

静态成员函数

1) 声明:在类的成员函数返回值之前加上关键字static,他就被声明为一个静态成员函数。静态成员函数不能声明为const或volatile,这与非静态成员函数不同。

2) 定义:出现在类体外的函数定义不能指定关键字static。

3) 作用:主要用于对静态数据成员的操作。

4) 静态成员函数与类相联系,不与类的对象相联系。

5) 静态成员函数不能访问非静态数据成员。因为非静态数据成员属于特定的类实例。

6) 静态成员函数没有this指针,因此在静态成员函数中隐式或显示的引用这个指针都将导致编译时刻错误。试图访问隐式引用this指针的非静态数据成员也会导致编译时刻错误。

7) 访问:可以用成员访问操作符(.)和箭头(->)为一个类对象或指向类对象的指针调用静态成员函数,也可以用限定修饰符名直接访问或调用静态成员函数,而无需声明类对象。

二、C/C++中static用法小结

1 C/C++中static关键字主要有三种使用方式, 其中第三种只在C++中使用:
  (1)局部静态变量
  (2)全局静态变量/函数
  (3)静态数据成员/成员函数

2 下面就这三种使用方式分别说明
  (1)局部静态变量
在C/C++中, 局部变量按照存储形式可分为三种auto(普通), static(静态), register(寄存器)
static局部变量与auto类型(普通)局部变量相比 有以下差别:

  • 存储空间分配不同
    auto类型分配在栈上, 属于动态存储类别, 占动态存储区空间, 函数调用结束后自动释放,
    而static分配在静态存储区, 在程序整个运行期间都不释放.
  • static局部变量在所处函数初次运行时完成初始化工作, 且只操作一次,auto类型(普通)局部变量在所处函数每次运行时动态存储区空间
  •  对于局部静态变量, 如果不赋初值, 编译期会自动赋初值0或空字符,而auto类型的初值如果不赋初值,是不确定的. (对于C++中的class对象例外, class的对象实例如果不初始化, 则会自动调用默认构造函数, 不管是否是static类型)
    (2)全局静态变量/函数
    为了限制全局变量/函数不能被其它文件访问,全局变量/函数前加static使得函数成为 全局静态函数。但此处“static”的含义不是指存储方式,而是指对函数的作用域仅局限于所处文件。
    使用全局静态变量/函数的好处是:不同的人编写不同的全局变量/函数时,不用担心自己定义的全局变量/函数,是否会与其它文件中的函数同名。
    (3)静态数据成员/成员函数(C++特有)
    C++重用了这个关键字,并赋予它与前面不同的第三种含义:表示属于一个类而不是属于此类的任何特定对象的变量/函数。这是与普通成员变量/成员函数的最大区别。在这里面, static既不是限定作用域的, 也不是扩展生存期的作用, 而是指示变量/函数在此类中的唯一性.

  

扩展阅读:[1]  

                   [2]

          [3] 

代码1:

Code:

 结果1:

times:0 localStaticObj:1
times:1 localStaticObj:2
times:2 localStaticObj:3
times:3 localStaticObj:4
times:4 localStaticObj:5
Press any key to continue

补充:

    《每天10分钟轻松掌握C++(第2版)》P67

     11.2.2 静态局部变量

     普通的局部变量在函数调用时创建,在函数结束时销毁。与之不同的是,静态变量在程序开始时创建和初始化,直到程序结束时才销毁(全局静态变量是程序开始的时候初始化,而局部静态变量则是在程序第一次执行到其声明的地方时初始化,且只初始化一次)。实际上,静态局部变量很像全局变量,但静态局部变量隐藏于函数体内,外部无法访问。所以静态局部变量不像使用全局变量那样容易引入缺陷。
 

 

 

显示全文