zoukankan      html  css  js  c++  java
  • c++中的静态类型 static

    static根据上下文语意有两种含义,一种是在类和结构体内,另一种时类在结构体外。

    类外的static在链接阶段是局部的,它只对它的编译单元(.obj)可见,而类内的static表示这个变量将在类内与所有实例共享

    Static.cpp

    static int s_Variable=5;

    main.cpp

    #include<iostream>
    
    int s_Variable=10;
    
    int main()
    {
        std::cout<<s_Variable<<std::endl;
        std::cin.get();
    }

    程序的运行结果是打印10,如果将Static.cpp中的static去掉,直接变成int声明变量s_Variable,那么在链接时会报错,因为s_Variable已经在另一个编译单元中被定义了,两个全局变量的名字不能一样,改正方法是使用引用

    Static.cpp

    int s_Variable=5;

    main.cpp

    #include<iostream>
    
    extern int s_Variable;
    
    int main()
    {
        std::cout<<s_Variable<<std::endl;
        std::cin.get();
    }

    extern的意思是在另外的编译单元中寻找定义,也叫外部链接,此时运行可以看到打印结果是5。加上static有些类似于在类中声明私有类型成员,其他的编译单元(.obj)不能访问s_Variable,函数也是一样。

    Static.cpp

    void function()
    {}

    main.cpp

    #include<iostream>
    
    int function()
    {}
    
    int main()
    {
        std::cin.get();
    }

    此时编译会发生错误,因为function被重复定义,如果将Static.cpp中的function前面加上static,那么链接将不会出错。

    在头文件中使用静态变量也是同样的道理,头文件相当于在引用头文件的位置将头文件的内容复制粘贴,因此头文件中使用static定义的静态变量即使在两个不同的cpp文件中被调用,也不会引起重复定义,因为它相当于在两个cpp文件中各自建立一个静态变量,互不干扰。

    因此尽量让全局变量和函数变成静态类型,除非要在别的cpp文件中调用它

    static在类和结构内代表什么

    表示类内所有同名变量都代表一个实体,如果这个尸体的值发生了改变,那么类中所有的这个实体都同样会改变。

    #include<iostream>
    
    struct Entity{
        int x,y;
        void Print()
        {
            std::cout<<x<<","<<y<<std::endl;
        }
    };
    
    int main()
    {
        Entity e;
        e.x=2;
        e.y=3;
        Entity e1={5,8};
        e.Print();
        e1.Print();
        std::cin.get();
    }

    打印结果是2,3   5,8  

    #include<iostream>
    
    struct Entity{
        static int x,y;
        void Print()
        {
            std::cout<<x<<","<<y<<std::endl;
        }
    };
    
    int Entity::x;
    int Entity::y;
    
    int main()
    {
        Entity e;
        e.x=2;
        e.y=3;
        Entity e1;
        e1.x=5;
        e1.y=8;
        e.Print();
        e1.Print();
        std::cin.get();
    }

    此时的打印结果是两个5,8,需要注意的是静态变量无法访问非静态变量,如果代码做如下修改,那么静态函数Print将无法访问非静态的变量x和y

    #include<iostream>
    
    struct Entity{
        int x,y;
        static void Print()
        {
            std::cout<<x<<","<<y<<std::endl;
        }
    };
    
    int main()
    {
        Entity e;
        e.x=2;
        e.y=3;
        Entity e1;
        e1.x=5;
        e1.y=8;
    
        Entity::Print();
        std::cin.get();
    }

    使用访问命名空间的方法来访问类/结构体中的静态成员是因为静态类型是唯一的,无需通过新建类/结构体来实现访问。如果做以下修改,可以正常运行

    #include<iostream>
    
    struct Entity{
        int x,y;
        static void Print()
        {
            std::cout<<x<<","<<y<<std::endl;
        }
    };
    
    static void Print(Entity e)
    {
        std::cout<<e.x<<","<<e.y<<std::endl;
    }
    
    int main()
    {
        Entity e;
        e.x=2;
        e.y=3;
        Entity e1;
        e1.x=5;
        e1.y=8;
    
        Print(e);
        std::cin.get();
    }

    本地作用域中(local scope)的静态变量

    需要掌握的变量的生命周期(变量在被删除之前在内存中存储多久)和作用域(在哪里可以访问到这个变量)

    局部静态变量允许我们定义一个生命周期是整个程序的变量,但是他的作用域被限制在当前函数中,其实也不一定是函数,可以在任何作用域中声明静态变量,函数中的静态变量和类中的静态变量其实没有很大的区别,他们的生命周期是一样的,唯一区别是类中的静态变量可以被类内的任何变量访问,在函数作用域中声明的静态变量,对于函数来说是局部的,就像类的静态变量对于类来说也是局部的。如果在函数中声明一个静态变量,那么在第一次调用函数时,这个静态变量被创建,后续再次调用此函数时将不会在创建这个变量。

    #include<iostream>
    
    void func()
    {
        int i=0;
        i++;
        std::cout<<i<<std::endl;
    }
    
    int main()
    {
        func();
        func();
        func();
        std::cin.get();
    }

    此函数的输出结果是三个1,如果将int i=0改为静态变量,那么结果将输出1,2,3

    #include<iostream>
    
    void func()
    {
        static int i=0;
        i++;
        std::cout<<i<<std::endl;
    }
    
    int main()
    {
        func();
        func();
        func();
        std::cin.get();
    }

    将i设在函数外面作为全局变量也是一样的结果,但是当i作为全局变量时,就意味着我在任何地方都可以调用它,所以会有一些意外的发生。

    #include<iostream>
    
    static int i=0;
    
    void func()
    {
        i++;
        std::cout<<i<<std::endl;
    }
    
    int main()
    {
        func();
        i=10;
        func();
        func();
        std::cin.get();
    }

    此时输出结果是1,11,12,如果不想让程序出现这种效果,此时可以将i变成局部静态变量

    同样,局部静态变量可以简化代码

    #include<iostream>
    
    class Singleton{
    private:
        static Singleton* s_Instance;
    public:
        static Singleton& get() {return s_Instance;}
        void Hello() {}
    };
    
    Singleton *Singleton::s_Instance=NULL;
    
    int main()
    {
        Singleton::Get().Hello();
        std::cin.get();
    }

    简化如下

    #include<iostream>
    
    class Singleton{
    public:
        static Singleton& get() 
        {
            static Singleton instance;
            return instance;
        }
        void Hello() {}
    };
    
    
    int main()
    {
        Singleton::Get().Hello();
        std::cin.get();
    }

    如果Singleton instance前面没有static,因为Singleton是在堆栈上建立的,在运行到结束花括号时被销毁,函数结束,在返回引用时这将会是个严重的错误,如果将表示引用的“&”去掉将不会有错,加上了static将会大大延长了instance的生命周期,每次调用get()的时候后面的调用都会返回到第一次构造的Singleton实例。

  • 相关阅读:
    jQuery右键菜单contextMenu使用实例
    如何调动员工的积极性 -引用LTP.Net知识库
    Linux 目录管理的相关命令
    linux bash基础特性
    Linux 文件系统简介(FHS:Filesystem Hierarchy Standard)
    Linux 基础命令
    docker 限制容器能够使用的资源
    docker 私有registry harbor安装
    docker Dockerfile里使用的命令说明
    docker 存储卷 Volumes
  • 原文地址:https://www.cnblogs.com/wangtianning1223/p/12669376.html
Copyright © 2011-2022 走看看