标签:
1. static的作用
不考虑类,static的作用主要有三条。
1.1 第一个作用:隐藏
当我们同时编译多个文件时,所有未加static前缀的全局变量和函数都具有全局可见性。
如果加了static,就会对其他源文件隐藏。利用这一特性可以在不同的文件中定义同名函数和同名变量,而不必担心命名冲突。
【示例】在一个cpp文件里,定义了一个static类型的全局变量,下面的描述中正确的是(A)。(腾讯)
A. 只能在该cpp所在的编译模块中使用该变量
B. 该变量的值是不可改变的
C. 该变量不能在类的成员函数中引用
D. 该变量只能是基本类型(如int, char),不能是C++类型
1.2 第二个作用:默认初始化为0
static的第二个作用是默认初始化为0,包括未初始化的全局静态变量与局部静态变量。其实未初始化的全局变量也具备这一属性,因为未初始化的全局变量与未初始化的静态变量是存储在同一块区域的(BSS段)。
在BSS段中,内存中所有的字节默认值都是0x00,某些时候这一特点可以减少程序员的工作量。比如初始化一个稀疏矩阵,我们可以一个一个地把所有元素都置0,然后把不是0的几个元素赋值。如果定义成静态的,就省去了一开始置0的操作。再比如要把一个字符数组当字符串使用,但又觉得每次在字符数组末尾加‘\0‘太麻烦。如果把字符串定义成静态的,就省去了麻烦,因为那里本来就是‘\0‘。
【示例】下列数组的值是什么?
1 string sa[10]; 2 static int ia[10]; // 也可不加static 3 int main() 4 { 5 string sa2[10]; 6 int ia2[10]; 7 }
【解答】
sa和sa2为元素类型为string的数组,自动调用string类的默认构造函数将各元素初始化为空字符串;ia为在函数体外定义的数组,各元素初始化为0;ia2为在函数体内定义的内置数组,各元素未初始化,其值不确定。
1.3 static的第三个作用:保持局部变量内容的持久
函数内的自动(局部)变量,当调用时就存在,退出函数时就消失,但静态局部变量虽然在函数内定义,但静态局部变量始终存在着,也就是说它的生存期为整个源程序,其特点是只进行一次初始化且具有"记忆性"。
静态局部变量的生存期虽然为整个源程序,但是其作用域与局部变量相同,即只能在定义该变量的函数内使用该变量。退出该函数后,尽管该变量还继续存在,但不能使用它。
【示例】以下代码的输出结果是什么?
1 #include <iostream> 2 using namespace std; 3 4 int count = 3; 5 6 int main(int argc, char *argv[]) 7 { 8 int i, sum, count = 2; 9 for (i = 0, sum = 0; i < count; i += 2, count++) 10 { 11 static int count = 4; 12 count++; 13 if (i % 2 == 0) 14 { 15 extern int count; 16 count++; 17 sum += count; // 语句1 18 } 19 sum += count; // 语句2 20 } 21 cout << count << " " << sum << endl; 22 return 0; 23 }
【解答】 4 20。
主要考查各个count的作用范围,for循环判断条件的count是main下第一行的count,for循环里面的count是static的count,if语句里面的count是main外部的count(extern int count语句的作用),语句2中的count是static的count,cout语句中的count是main下第一行的count。
2. 类中static的作用
C++重用了static这个关键字,并赋予它与前面不同的含义:表示属于一个类而不是属于此类的的任何特定对象的变量和函数(与Java中此关键字的含义相同)。
static成员可以是函数或数据,都独立于类类型的对象而存在。
2.1 静态数据成员
在类内数据成员的声明前加上关键字static,该数据成员就是类内的静态数据成员。通常,非static数据成员存在于类类型的每个对象中。不像普通的数据成员,static数据成员独立于该类的任意对象而存在;每个static数据成员是与类关联的对象,并不与该类的对象相关联,也就是说当某个类的实例修改了该静态成员变量,其修改值为该类的其他所有实例所见。
静态数据成员和普通数据成员一样遵从public,protected,private访问规则。
静态数据成员也存储在全局(静态)存储区。静态数据成员定义时要分配空间,所以不能在类声明中定义。static数据成员必须在类定义体的外部定义(正好一次)。
一般而言,类的static成员,像普通数据成员一样,不能在类的定义体中初始化,static数据成员通常在定义体的外部定义时才初始化,即在类定义体中对静态变量赋初值是错误的。这个规则有一个例外:基本整型const static数据成员可以在类的定义体中进行初始化。
基本整型const static数据成员在类的定义体中初始化时,该数据成员仍必须在类的定义体之外进行定义,只不过定义时,不再需要初始化。
2.2 静态成员函数
静态成员函数与静态数据成员一样,都是类的内部实现,属于类定义的一部分,它为类服务而不是为某一个类的具体对象服务。
因为普通成员函数总是具体的属于某个类的具体对象,所以普通的成员函数一般都隐含了一个this指针,this指针指向类的对象本身。
但是与普通成员函数相比,静态成员函数由于不与任何的对象相关联,因此它不具有this指针。因而它无法访问属于类对象的非静态数据成员,也无法访问非静态成员函数,它只能调用其余的静态成员函数与访问静态数据成员。
因为static成员不是任何对象的组成剖分,所以static成员函数不能被声明为const。毕竟,将成员函数声明为const就是承诺不会修改该函数所属的对象,而static成员函数不属于任何对象。
最后,static成员函数不能被声明为虚函数、volatile。
关于静态成员函数,可以总结为以下几点:
1) 静态成员函数之间可以相互访问,包括静态成员函数访问静态数据成员和访问静态成员函数。静态成员函数不能访问非静态成员函数和非静态数据成员,非静态数据成员函数可以任意地访问静态成员函数和静态数据成员;
2) 由于没有this指针的额外开销,因此静态成员函数与类的非静态成员函数相比速度上会有少许的增长。
标签:
原文地址:http://www.cnblogs.com/xiaoxxmu/p/5455112.html