static用法总结

从C到C++。

***************************************************
C语言中用法:

全局静态变量:
作用: 改变变量的作用域
内存:不变,全局变量本来就是存放在静态存储区(初始化数据段或非初始化数据段)
初始化:未经初始化的全局静态变量将被自动初始化为0(内核 or 编译器来做?)
作用域:限定作用域为文件内从定义之处开始到文件结尾 (非静态全局变量在整个源程序内有效)。

C语言中这样做有两个好处:
1)不会被其他文件所访问,修改
2)其他文件中可以使用相同名字的变量,不用担心命名冲突
在C++中,这种方法将逐步被命名空间取代。

局部静态变量:
作用: 改变存储方式(同时也改变了生存期,与该特性相对的是auto, register)
内存:静态存储区
初始化: static局部变量在所处模块在初次运行时进行初始化工作, 且只操作一次
作用域:不变

静态函数:在函数的返回类型前加上关键字static
作用: 改变作用域,与之相对的是extern(缺省情况)
内存:代码段
作用域:限定作用域为文件内

好处:
同静态全局变量一样,即可以禁止其他编译单元的调用,又能屏蔽可能存在的外部的同名函数,不要担心命名冲突
(跟普通的函数比仅仅是限制了作用域而已, 这个有待阅读C语言标准,想要调用还是可以的,通过函数指针;也有网友说静态函数所做的只是在汇编的时候把.globe符号给去掉了使得静态函数只在当前的文件中生效,有待继续看书)

补充:(基于个人的理解)
1):这几个关键词
auto,register,static这几个关键词在C语言中可以用来声明 存储类型
同时呢,extern,static还可以用来声明编译与链接方式,从而改变作用域(要知道C/C++是以.c/.cpp/.cc文件为编译单元的,static修饰的函数与变量是不会出现在源文件编译后的导出符号表的,“extern C”{}用来声明函数名称在导出符号表中的修饰方式);

2)局部静态变量的初始化
从方便理解的角度,可以将初始化语句看成声明与赋值两个步骤,声明涉及存储的分配,而赋值步骤只进行一次;
有些会出现重复调用的则属于C语言的未定义行为: C++03 6.7:
The zero-initialization (8.5) of all local objects with static storage duration (3.7.1) is performed before any other initialization takes place. A local object of POD type (3.9) with static storage duration initialized with constant-expressions is initialized before its block is first entered. An implementation is permitted to perform early initialization of other local objects with static storage duration under the same conditions that an implementation is permitted to statically initialize an object with static storage duration in namespace scope(3.6.2). Otherwise such an object is initialized the first time control passes through its declaration; such an object is considered initialized upon the completion of its initialization. If the initialization exits by throwing an exception, the initialization is not complete, so it will be tried again the next time control enters the declaration. If control re-enters the declaration (recursively) while the object is being initialized, the behavior is undefined. [Example:
int foo(int i)
{
static int s = foo(2*i); // recursive call – undefined
return i+1;
}
上面例子在VS2010下调用foo(1)的结果是:s值为3,返回值为2。第一次调用该函数,为s分配内存单元,为进行赋值需再调用该函数,压栈保护现场,第二次进入时s已存在,则跳过初始化语句,返回3,退栈,将3赋值给s,返回2。

3)还是关于初始化
auto变量的初始化值是任意的,除非他被显示初始化;而C++中的类对象例外,在没用调用指定构造函数时,就调用默认构造函数,不管是不是静态类型的对象。

4)对于静态变量的使用
要考虑不可重入性,及在多线程编程时的不安全性。

5)“C++ primer Plus”上
a. 编译器将分配固定的内存块来存储所有的静态变量,这些变量在整个程序执行期间一直存在。另外,如果没有显示地初始化静态变量, 编译器将把它设置为0。
(保留疑问,编译器设置数据段的内存单元为指定值,在程序运行时,操作系统是不是直接拷贝对应数据到内存单元?)
b.静态持续变量有三种链接特性:
外部链接性:int global = 100;  //代码块之外
                          int main()
内部链接性:static int one_file = 50; //代码块外,并用static声明
                          int main()
无链接性:    void foo(){
                          static int count = 0;   //代码块内,并用static声明
上面三种变量在程序的整个执行期间都存在;最后一种,只能在foo函数内使用。

***************************************************
C++中新增的用法:
C++重用了这个关键字,并赋予它与前面不同的第三种含义:表示属于一个类而不是属于此类的任何特定对象的变量和函数。

静态成员变量:两种情况(存放在不同的区域,见const总结)
1)常量:
class  Stock
{
private :
                  static  const  int  Len = 30;
}

2)非常量:  “C++ primer Plus” P380
class  String
{
private :
                  static  int  num_strings; 
}

不能在类声明中初始化该静态成员变量!!否则会报错 “只有静态常量整型数据成员才可以在类中初始化”,
“C++ primer Plus”中解释,这是因为类声明描述了如何分配内存,但并不分配内存。类的静态成员是单独存储的,而不是对象的组成部分。
个人理解,首先区分声明和定义,定义涉及内存分配,静态类型变量只能被定义一次,然后被所有对象共享,而不是在每个对象中都定义一次。

初始化可如下进行(在实现文件中):
int  String::num_strings = 0;    //注意使用作用域操作符

而且一旦在程序中使用到该变量,就 必须先进行初始化,否则会出现链接错误,如main中有:
cout<<String::num_strings;
个人理解,其实是必须定义(分配内存单元),并在定义时赋予值,因为类只是声明对象形式,不分配内存(除了上面的常量的情况)。

静态成员函数:(少用到)
静态成员函数的地址可用普通函数指针储存,而普通成员函数地址需要用类成员函数指针来储存;
静态成员是可以独立访问的,也就是说, 无须创建任何对象实例就可以访问
静态成员函数不可以调用类的非静态成员(不管是成员变量还是成员函数), 因为静态成员函数不含this指针(this指针只传给非静态成员函数,这一点很重要)。

***************************************************
一些笔试题目:
1.关于static变量,请选择下面所有说法正确的内容:
A、若全局变量仅在单个C文件中访问,则可以将这个变量修改为静态全局变量,以降低模块间的耦合度;
B、若全局变量仅由单个函数访问,则可以将这个变量改为该函数的静态局部变量,以降低模块间的耦合度;
C、设计和使用访问动态全局变量、静态全局变量、静态局部变量的函数时,需要考虑重入问题;(函数是可重入的是指只要输入数据相同就应产生相同的输出)
D、静态全局变量过大,可那会导致堆栈溢出。

2.下列关于一个类的静态成员的描述中,不正确的是(D)(TX笔试题)
A、该类的对象共享其静态成员变量的值                              B、静态成员变量可被该类的所有方法访问                 
C、该类的静态方法只能访问该类的静态成员变量                 D、该类的静态数据成员变量的值不可修改

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值