c++ static、extern

一、static本质作用

      与static相对的关键字是auto,两者是一对。我们一般声明变量,如:int a,其实都是auto int a,只是auto省略了而已,但是static不能省略。要理解static,最好先理解auto。auto的含义是由程序自动控制变量的生存周期,通常是变量在进入其作用域的时候被分配,离开其作用域的时候被释放;而static则不同,变量在程序初始化时被分配,直到程序退出前才被释放;也就是static是按照程序的生命周期来分配释放变量的,而不是按照变量自己的生命周期。

二、static用法

1.局部变量

如:void func()  

{  

int a; 

static int b;  

}

      就算函数结束了,b的值也能够一直保持。每一次调用该函数,变量a都是新的,因为它是在进入函数体的时候被分配,退出函数体的时候被释放,所以多个线程调用该函数,都会拥有各自独立的变量a,因为它总是要被重新分配的;而变量b不管你是否使用该函数,在程序初始化时就被分配的了,或者在第一次执行到它的声明的时候分配(不同的编译器可能不同),所以多个线程调用该函数的时候,总是访问同一个变量b,这也是在多线程编程中必须注意的!

      一般情况下,对于局部变量是存放在栈区的,并且局部变量的生命周期在该语句块执行结束时便结束了。但是如果用static进行修饰的话,该变量便存放在静态数据区,其生命周期一直持续到整个程序执行结束。但是在这里要注意的是,虽然用static对局部变量进行修饰过后,其生命周期以及存储空间发生了变化,但是其作用域并没有改变,其仍然是一个局部变量,作用域仅限于该语句块。

2.类的静态数据成员

  class A

  {

     private:

   static int s_value;

};

  类的静态成员必须初始化才能使用,因为它是在程序初始化的时候分配的,所以必须有初始化,类中只是声明,在cpp中才是初始化,静态成员初始化与一般数据成员初始化不同。静态数据成员初始化的格式如下:

 int A::s_value = 0;//<数据类型><类名>::<静态数据成员名>=<值>,注意,这里没有static的修饰!

 使用静态成员时,可以通过双冒号(即<类名>::<静态成员名>,也可以通过对象调用)。

 类的静态成员是该类所有实例的共用成员,也就是在该类的范畴内是个全局变量,也可以理解为是一个名为A::s_value的全局变量,只不过它是带有类安全属性的。道理很简单,因为它是在程序初始化的时候分配的,所以只分配一次,所以就是共用的。

3.类的静态成员函数

class A 

 { 

    private:

        void init();

        static void output();

};

void main()
    {
        A::init();
        A::output();
    }//A::init();会出错,因为不能通过类名来调用类的非静态成员函数。

void main()
    {
       A pt;
       pt.init();
       pt.output();
    }//编译通过,因为类的对象可以使用静态成员函数和非静态成员函数。

 静态成员函数和静态数据成员一样,它们都属于类的静态成员,不是对象成员。因此,对静态成员的引用不需要用对象名,当然,通过对象来使用也可以。在静态成员函数的实现中不能直接引用类的非静态成员,可以引用类中的静态成员。如果静态成员函数中要引用非静态成员时,可通过对象来引用。因为静态成员函数属于整个类,在类实例化对象之前就已经分配空间了,而类的非静态成员必须在类实例化对象后才有内存空间,所以调用就会出错,就好比没有声明一个变量却提前使用它一样。

 实现的时候也不需要static的修饰,因为static是声明性关键字;类的静态函数是在该类的范畴内的全局函数,实际上,它就是增加了类的访问权限的全局函数:void A::output();

注意:静态成员函数可以继承和覆盖,但无法是虚函数;在类的非静态成员函数中可以使用类的静态成员。

4.文件内全局变量

若在cpp中有,static int g_value = 0;

这个变量的含义是在该cpp内有效,其他的cpp文件不能访问这个变量;如果有两个cpp文件声明了同名的全局静态变量,那么他们实际上是独立的两个变量;如果不使用static声明全局变量:int g_value = 0;那么将无法保证这个变量不被别的cpp共享,也无法保证一定能被别的cpp共享,看有没有extern。

5.普通函数

即静态函数,它只能在声明它的文件当中可见,不能被其它文件使用。

三、extern

   extern用在变量或者函数的声明前,用来说明“此变量/函数是在别处定义的,可能是在别的文件,也可能是在本文件当前位置的后面,但是要在此处引用”。在这里要注意extern声明的位置对其作用域也有关系,如果是在main函数中进行声明的,则只能在main函数中调用,在其它函数中不能调用。其实要调用其它文件中的函数和变量,只需把该文件用#include包含进来即可,为啥要用extern?因为用extern会加速程序的编译过程,这样能节省时间

1.cpp文件中

  1. file1.cpp 
  2. int a=1; 

  3.  
  4. file2.cpp  
  5. #include<stdio.h> 
  6. extern int a;  
  7. int main(void)  
  8. {  
  9. printf("%d\",a);  
  10. return 0;  
     这样,file2就可以用file1中的int a了, 但是如果在file1中把int a=1改为static int a=1;那么在file2是无法访问到变量a的。原因在于用static对全局变量进行修饰改变了其作用域的范围,由原来的整个工程可见变为本源文件可见。

2.指示调用规范

      在C++中extern还有另外一种作用,用于指示C或者C++函数的调用规范。比如在C++中调用C库函数,就需要在C++程序中用extern “C”声明要引用的函数。这是给链接器用的,告诉链接器在链接的时候用C函数规范来链接。主要原因是C++和C程序编译完成后在目标代码中命名规则不同,用此来解决名字匹配的问题。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值