C/C++中static详解

C语言中:

静态变量作用范围在一个文件内,程序开始时分配空间,结束时释放空间,默认初始化为0,使用时可以改变其值

    静态变量或静态函数只有本文件内的代码才能访问它,它的名字在其它文件中不可见。
用法1:函数内部声明的static变量,只在本函数内有效,函数只分配一次内存,不初始化,其值为0,函数返回时,该变量不会消失!

用法2:函数外部申明的static变量,只在本文件内有效,如果不初始化,则为0.

用法3:将函数申明为static,则该函数也只能在本文件使用!

 进一步详细解释如下:

1.先来介绍它的第一条也是最重要的一条:隐藏

     当我们同时编译多个文件时,所有未加static前缀的全局变量和函数都具有全局可见性。为理解这句话,我举例来说明。我们要同时编译两个源文件,一个是a.c,另一个是main.c. 下面是a.c的内容:

static int i = 10;   // global variable

void msg()

{

         printf("i = %d\n", i++);

}

    下面是main.c的内容:

extern int i;    //extern ariable must be declared before use

int main(void)

 { 

      printf("%d ", i);

      msg();

      return 0; 

 }

    程序的运行结果是:

编译通过,运行出现错误,原因就是static变量只能在在本文件中使用,若改动将a.c文件中的static去掉,或去掉main.c中的extern,这样两个问津中的i也是不同的两个变量!

验证static变量的生命周期:

int fun(int a)

{

       static int i;

       i += a;

       printf("%d\n", i);

}

int main()

{

      int a = 10;

      fun(a);

      fun(a);

      fun(a);

      return 0;

}

可知运行结果为20 30 40;若去掉static 则结果为20 20 20

2. static的第二个作用是保持变量内容的持久

3. static的第三个作用是默认初始化为0.其实全局变量也具备这一属性,因为全局变量也存储在静态数据区

    最后对static的三条作用做一句话总结。首先static的最主要功能是隐藏,其次因为static变量存放在静态存储区,所以它具备持久性和默认值0.

4. 用static声明的函数和变量小结

    static 声明的变量在C语言中有两方面的特征:

1)、变量会被放在程序的全局存储区中,这样可以在下一次调用的时候还可以保持原来的赋值。这一点是它与堆栈变量和堆变量的区别。

2)、变量用static告知编译器,自己仅仅在变量的作用范围内可见。这一点是它与全局变量的区别。

Tips:
A.若全局变量仅在单个C文件中访问,则可以将这个变量修改为静态全局变量,以降低模块间的耦合度;
B.若全局变量仅由单个函数访问,则可以将这个变量改为该函数的静态局部变量,以降低模块间的耦合度;
C.设计和使用访问动态全局变量、静态全局变量、静态局部变量的函数时,需要考虑重入问题;
D.如果我们需要一个可重入的函数,那么,我们一定要避免函数中使用static变量(这样的函数被称为:带“内部存储器”功能的的函数)
E.函数中必须要使用static变量情况:比如当某函数的返回值为指针类型时,则必须是static的局部变量的地址作为返回值,若为auto类型,则返回为错指针。

    从以上分析可以看出, 把局部变量改变为静态变量后是改变了它的存储方式即改变了它的生存期。把全局变量改变为静态变量后是改变了它的作用域, 限制了它的使用范围。

(1) static 函数与普通函数作用域不同。仅在本文件。只在当前源文件中使用的函数应该说明为内部函数(static),内部函数应该在当前源文件中说明和定义。对于可在当前源文件以外使用的函数,应该在一个头文件中说明,要使用这些函数的源文件要包含这个头文件

(2) static全局变量与普通的全局变量有什么区别:static全局变量只初始化一次,防止在其他文件单元中被引用;

(3) static局部变量和普通局部变量有什么区别:static局部变量只被初始化一次,下一次依据上一次结果值;
(4) static函数与普通函数有什么区别:static函数在内存中只有一份,普通函数在每个被调用中维持一份拷贝.
(5) 全局变量和静态变量如果没有手工初始化,则由编译器初始化为0。局部变量的值不可知。

5. C++的static

  静态成员函数的特点是:不管这个类创建了多少个对象,其静态对象在内存中之保留一份拷贝,这个拷贝为该类的所有对象共享。

1.静态数据成员

类的普通成员在类的每一个对象中都有一个拷贝,静态数据成员是类的一种特例采用static修饰,属于类属性,每一个只有一个拷贝,由该类的所有对象共同维护和使用,从而实现了同类的不同对象之间的数据共享

静态数据成员的定义分为两个必不可少的部分:类内申明,类外初始化

申明:static 数据类型 静态数据成员名;

初始化:数据类性 类名::静态数据成员名=初始化;

注意事项:

a.静态数据成员脱离具体对象而独立存在,其存储空间是独立分配的,不是任何对象对象存储空间的一部分

b.静态数据成员在程序开始时产生,在程序结束时消失,具有静态生存期

c.在类外对静态数据成员初始化,必须使用类作用域运算符::限定它所属类

访问静态数据成员:

a.与普通成员变量一样,可以通过对象,对象指针,对象引用来访问

b.类名::静态成岩变量

 

2.静态成员函数

静态数据成员为类属性,在定义类后,建立对象前就存在。因此建立对象前不能通过成员函数存取静态数据成员。C++提供了静态成员函数,它用来存取类的静态成员,它属于整个类而不属于类中的某个对象,是该类的所有对象共享的成员函数。

静态成员函数可以在类内定义,也可以在类内申明为static,在类外定义,此时不用加static

 

关于静态成员函数,可以总结为以下几点:
a. 出现在类体外的函数定义不能指定关键字 static;
b. 静态成员之间可以相互访问,包括静态成员函数访问静态数据成员和访问静态成员函数;
c. 非静态成员函数可以任意地访问静态成员函数和静态数据成员;
d. 静态成员函数不能访问非静态成员函数和非静态数据成员;
e. 由于没有 this 指针的额外开销, 因此静态成员函数与类的全局函数相比速度上会有少许 的增长;
f. 调用静态成员函数,可以用成员访问操作符(.)和(->)为一个类的对象或指向类对象的指针调用静态成员函数;

普通的成员函数一般都隐含了一个 this 指针,this 指针指向类的对象本身,

因为普通成员函数总是具体的属于某个类的具体对象的。通常情况下,this 是缺省的。但是与普通函数相比,静态成员函数由于不是与任何的对象相联系,因此它不具有 this 指针,从这个意义上讲,它无法访问属于类对象的非静态数据成员,也无法访问非静态成员函数,  它只能调用其余的静态成员函数。

 

#include <iostream.h>
class Myclass
{
public:
     Myclass(int a,int b,int c);
     static void GetSum();//声明静态成员函数
private:
     int a,b,c;
     static int Sum;//声明静态数据成员
};
int Myclass::Sum=0;//定义并初始化静态数据成员
Myclass::Myclass(int a,int b,int c)
{
     this->a=a;
     this->b=b;
     this->c=c;
Sum+=a+b+c; //非静态成员函数可以访问静态数据成员
}
void Myclass::GetSum() //静态成员函数的实现
{
     // cout < <a < <endl; //错误代码,a 是非静态数据成员
     cout <<"Sum=" <<Sum <<endl;
}
int main()
{
     Myclass M(1,2,3);
     M.GetSum();
     Myclass N(4,5,6);
     N.GetSum();
  Myclass::GetSum();
   return 0;
}

 

 

 

 

 

 

 

 

 

 

 

  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值