• C/C++中的static


    一、静态全局变量

    理解static关键字之前首先回顾一下C/C++程序的在内存中的分配情况。从低地址到高地址依次分为:代码区、全局数据区、堆区、栈区。函数之外的全局变量和静态变量(包括全局变量和静态变量)都存储在全局数据区,堆区有程序员自己通过malloc,new申请内存,栈区存放函数内部的临时变量,随着函数的退出而释放内存。

    静态全局变量和普通全局变量的区别:

    • 静态全局变量和普通全局变量都存储在全局变量区,在这一点两者是相同的。
    • 普通全局变量的作用域是整个工程,在某个文件中定义的全局变量,被其它文件引用时,在开头处用extern标明使用的外部变量即可。而静态全局变量的作用域是定义该变量的文件,无法在外部文件引用。

    例如:当n是全局变量是可以正常通过的,当n定义为静态全局变量是无法编译通过的

    //Example2
    //File1第一个代码文件的代码
    #include<iostream>
    #include "example2.h"
    int n;  //定义静态全局变量
    void main()
    {
        n=20;
        std::cout<<n<<std::endl; //20
        fn(); //21
    }
    //File2第二个代码文件的代码
    #include<iostream.h>
    extern int n;
    void fn()
    {
        n++;
        std::cout << n << endl;
    }

    二、静态局部变量

    我们知道定义在函数内部的局部变量存放在栈区,随着程序退出函数,系统会回收栈内存,局部变量会失效。有些时候需要通过引入静态局部变量,将局部变量存放在全局数据区。静态局部变脸只在第一次初始化,每次的值保存到下一次调用,始终驻留在全局数据区,直到程序退出。静态全局变量的作用域没有改变,依然是局部的。

    #include<iostream>
    using namespace std;
    void fn();
    void main()
    {
        fn();
        fn();
        fn();
    }
    void fn()
    {
        static int n=10;
        cout << n << endl;
        n++;
    }

    三、静态函数

    关于静态函数限制函数作用域的做法,我C++试验了一下,发现已经不起作用了。另一方面确实很少使用,就不多讲了。C++面向对象中,比较关键的是静态成员、静态成员函数。

    四、静态成员变量

    • 对于非静态数据成员,每个类对象都有自己的拷贝。而静态数据成员被当作是类的成员。无论这个类的对象被定义了多少个,静态数据成员在程序中也只有一份拷贝,由该类型的所有对象共享访问,包括其派生类的对象。所以,静态数据成员的值对每个对象都是一样的,它的值可以更新;
    • 静态数据成员存储在全局数据区。静态数据成员定义时要分配空间,所以必须在类中申明,类外定义。例如在在下面的例子中,int Myclass::Sum=0;是定义静态数据成员
    • 静态数据成员和普通数据成员一样遵从public,protected,private访问规则;如果静态数据成员定义访问权限允许的话,定义为public;可以通过<类对象名>.<静态数据成员名> 或 <类类型名>::<静态数据成员名>访问公有静态成员
    全局变量相比,使用静态数据成员有两个优势:
    1. 静态数据成员没有进入程序的全局名字空间,因此不存在与程序中其它全局名字冲突的可能性;
    2. 可以实现信息隐藏。静态数据成员可以是private成员,而全局变量不能;
     1 #include<iostream>
     2 using namespace std;
     3 class Myclass {
     4 public:
     5     Myclass(int a, int b, int c);
     6     static void GetSum();  //声明静态成员函数
     7 private:
     8     int a, b, c;
     9     static int Sum; //声明静态数据成员
    10 
    11 };
    12 int Myclass::Sum = 0; //定义并初始化静态数据成员
    13 
    14 Myclass::Myclass(int a, int b, int c) {
    15     this->a = a;
    16     this->b = b;
    17     this->c = c;
    18     Sum += a + b + c;  //非静态成员函数可以访问静态数据成员
    19 }
    20 void Myclass::GetSum() {  //静态成员函数实现
    21     //cout << a << endl;  // error,a是非静态成员
    22     cout << "Sum=" << Sum << endl;
    23 }
    24 int main() {
    25     cout << sizeof(Myclass) << endl; //静态成员不占用对象空间
    26     Myclass M(1, 2, 3);
    27     M.GetSum();
    28     Myclass::GetSum();  //静态成员函数访问
    29     Myclass N(4, 5, 6);
    30     N.GetSum();
    31     M.GetSum();
    32     return 0;
    33 }

     五、静态成员函数

    • 和静态成员变量一样,也可以定义静态成员函数。静态成员函数为类的所有对象服务,不是为类的某个具体对象服务
    • 静态成员函数在类中声明,在类中类外事项都可以,在类外实现时,不能加static关键字。静态成员必须在类中声明,类外初始化
    • 静态成员之间可以相互访问,包括静态成员函数访问静态数据成员和访问静态成员函数;
      非静态成员函数可以任意地访问静态成员函数和静态数据成员;
      静态成员函数不能访问非静态成员函数和非静态数据成员;
    • 由于静态成员函数没有this指针,因此无法访问非静态成员和非静态成员函数
    • 静态成员函数的访问可以使用类的访问方式<类名::成员函数>或者对象成员的访问方式<对象.成员函数>、<对象指针->成员函数>
    • 静态成员函数不可以同时声明为 virtual、const、volatile函数
  • 相关阅读:
    JS 学习笔记
    Input控件只允许输入指定字符
    NPOI导出excel使用
    combobox级联检索下拉选择框
    vue父组件调用子组件方法
    EasyUI设置Layout自适应浏览器宽度和高度
    EasyUI创建选项卡并判断是否打开
    Jquery+ajaxfileupload上传文件
    Jquery禁用网页右键菜单
    c#删除指定文件夹中今天之前的文件
  • 原文地址:https://www.cnblogs.com/wxquare/p/6692924.html
Copyright © 2020-2023  润新知