一、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::init();会出错,因为不能通过类名来调用类的非静态成员函数。
    A::output();
  }

  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文件中

  file1.cpp

  int a=1;

  file2.cpp

  #include<stdio.h>

  extern int a;

  int main(void)

  {

    printf("%d\",a);

    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程序编译完成后在目标代码中命名规则不同,用此来解决名字匹配的问题。

C/C++ static、extern的更多相关文章

  1. 如何正确使用const、static、extern

    转自:http://www.jianshu.com/p/2fd58ed2cf55 前言 本篇文章主要介绍在开发中怎么使用const.static.extern关键字. 一.const 与宏的区别: c ...

  2. 88、const、static、extern介绍

    一.const与宏的区别 const简介:之前常用的字符串常量,一般是抽成宏,但是苹果不推荐我们抽成宏,推荐我们使用const常量. 执行时刻:宏是预编译(编译之前处理)const是编译阶段. 编译检 ...

  3. oc温习八:static、extern、const 的了解

    参考文章:http://www.cocoachina.com/ios/20161110/18035.html 1.const 这个单词翻译成中文是“常量”的意思.在程序中我们知道“常量”的值是不能变的 ...

  4. 【VS开发】static、extern分析总结

    引用请注明出处:http://blog.csdn.net/int64ago/article/details/7396325 对于写了很多小程序的人,可能static和extern都用的很少,因为sta ...

  5. C语言中volatile、register、const、static、extern、 auto关键字的作用

    一.volatile详解 volatile的本意是"易变的" 因为访问寄存器要比访问内存单元快的多,所以编译器一般都会作减少存取内存的优化,但有可能会读脏数据.当要求使用volat ...

  6. 关键字static、extern、volatile、详解及举例

    一.预备知识 1. 什么是局部变量?什么是全局变量?          所谓局部变量,就是指在函数内部定义的变量的,只在该函数范围内有效. 全局变量是指,在函数外部定义的变量为外部变量,即全局变量.它 ...

  7. const、static、extern三个关键字

    默认情况下,C语言的全局变量是全世界都可以访问的,也就是全局变量可以跨文件访问. extern可以引用全局变量 例如,如果有一个全局变量int money = 100;extern int money ...

  8. c语言中static、extern、void的重载

    static:   1.在函数内部,表示该变量的值在各个调用间一直保持延续性:     2.在函数这一级,表示该函数只对本文件可见. extern: 1.用于函数定义,表示全局可见(属于冗余的):   ...

  9. OC中使用 static 、 extern、 const使用

    static static用于定义静态变量,静态变量只会被初始化一次,并且直到程序销毁时才会释放 static NSString *str = @"asdfa"; const co ...

随机推荐

  1. SSD硬盘安装系统后要做的事

    1***cmd>fsutil behavior query DisableDeleteNotify 0如果返回值是0,则代表TRIM处于开启状态:反之如果返回值是1,则代表TRIM处于关闭状态2 ...

  2. Redis官网下载步骤(含windows版)

    ①.百度redis ,进入官网 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQk ...

  3. C++ auto 与 register、static keyword 浅析

    [register/auto的比較分析] #include <iostream> using namespace std; int main(){ int i,sum=0; for(i=0 ...

  4. Python爬虫【第3篇】【多线程】

    一.多线程 Python标准库提供2个模块,thread是低级模块,threading是高级模块 1.threading模块创建多线程 方式1:把1个函数传入并创建Thread实例,然后调用start ...

  5. Android学习笔记-获取手机内存,SD卡存储空间。

    前面介绍到如何保存数据到手机内存或者SD卡,但是问题是,在保存以前,我们还需要对他们的空间(可用空间),进行判断,才可以进行后续操作,所以,本节我们就介绍如何获取手机内存以及Sd卡的空间. //这时获 ...

  6. 安装 pip pip 包 安装路径

    python2 -m pip install --upgrade pip --force-reinstall pip uninstall pandas pip install --install-op ...

  7. curl HTTP_USER_AGENT

    [root@bigdata-server-01 ~]# curl 13.26.92.20array(27) { ["HTTP_USER_AGENT"]=> string(11 ...

  8. Ubuntu16.04下搭建开发环境及编译tiny4412 Android系统【转】

    本文转载自:http://blog.csdn.net/songze_lee/article/details/72808631 版权声明:本文为博主原创文章,未经博主允许不得转载. 1.安装ssh服务器 ...

  9. Oracle 游标使用总结(好文章)

    游标(CURSOR)也叫光标,在关系数据库中经常使用,在PL/SQL程序中可以用CURSOR与SELECT一起对表或者视图中的数据进行查询并逐行读取. Oracle游标分为显示游标和隐式游标. 显示游 ...

  10. lodop

    一.控件参数 Lodop有如下控件参数,以页面object对象元素的参数形式使用: Caption名称:设置控件的显示标题格式: < pa ram name="Caption" ...