zoukankan      html  css  js  c++  java
  • [C++]static详细说明

    static用于声明全局变量(包括类的对象),局部变量全局函数,类的成员变量成员函数。即,static不能用于类、结构、枚举、联合的声明。

    static有如下用途:

    ①使变量具有初值

    静态变量具有初值。局部变量是没有初值,而static的局部变量将有初值。全局变量本身就具有初始值,所以static不发生作用。static用于全局变量,更多是用于解决命名冲突问题。

    static确定初始值
    #include <iostream>
    
    void PrintNormal()
    {
        int i;
        double d;
        char c;
        int* p;
        std::cout << a << std::endl;
        std::cout << i << std::endl;    // output: -858993460
        std::cout << d << std::endl;    // output: -9.25596e+061
        std::cout << c << std::endl;    // output: (乱码)
        std::cout << p << std::endl;    // output: CCCCCCCC
    }
    
    void PrintStatic()
    {
        static int i;
        static double d;
        static char c;
        static int* p;
        std::cout << a << std::endl;
        std::cout << i << std::endl;    // output: 0
        std::cout << d << std::endl;    // output: 0
        std::cout << c << std::endl;    // output: (空)
        std::cout << p << std::endl;    // output: 00000000
    }
    
    int main()
    {
        PrintNormal();
        PrintStatic();
        system("pause");
    }

     

    ②声明全局变量

    如果一个变量在所有的块之外,那么这个变量是全局变量,具有static duration(即也有初始值)和external linkage特性。注意要使用extern关键字。如果两个编译单元都使用同名的全局变量,将报错。(Visual Studio中。Linux下参考强符号、弱符号)

    声明全局变量
    // external linkage
    int a;
    另一个文件使用之
    #include <iostream>
    extern int a;
    int main()
    {
        std::cout << a << std::endl;
        system("pause");
    }

    但是,用static修饰后,此变量将变为external linkage。无法被外部Link。

    声明全局静态变量
    // external linkage
    static int a = 5;
    另一个文件中使用将报错,可以声明同名的变量
    #include <iostream>
    static int a;
    // 将报错error LNK2001: 无法解析的外部符号 "int a" (?a@@3HA)
    //extern int a;
    int main()
    {
        std::cout << a << std::endl;
        system("pause");
    }

    然而,static不支持类、结构、枚举的修饰,比起static修饰,更推荐使用namespace解决命名冲突(参见匿名namespace)。

    ③声明全局函数

    全局函数类似,如果要改变其external linkage的特性,需要使用static。

    ④声明局部变量

    用static声明局部变量虽然不改变其可见性,但变量仍然是static duration的,在其可见域外,仍可以使用地址访问之。

    声明局部变量
    #include <iostream>
    int* p;
    void foo()
    {
        static int a;
        if (a == 0)
        {
            a = 10;
            p = &a;
        }
        a++;
    }
    void main()
    {
        foo();
        // 将报错,a不可见
        //std::cout << a << std::endl;
        std::cout << *p << std::endl; // 11
        *p = 20;
        foo();
        std::cout << *p << std::endl; // 21
        system("pause");
    }

    ⑤声明类的成员变量

    除了显然意见的作用外,有两个注意点:

    1. static的成员变量必须在file scope定义(即便不改变初值也要声明)

    出错举例
    #include <iostream>
    class A
    {
    public:
        static int a;
    };
    // 如果不定义,会报错
    /* error LNK2001: 无法解析的外部符号 "public: static int A::a" (?a@A@@2HA) */
    
    // 如果在定义时增加了static关键字,会报错
    /* error C2720: “A::a”: 成员上的“static ”存储类说明符非法 */
    //static int A::a;
    
    // 定义的时候可以指定初值
    int A::a = 5;
    
    void main()
    {
        std::cout << A::a << std::endl;
        system("pause");
    }

    2. 对于const static类型,除了以上方法外,还可以直接在类中初始化~不是const不成哦~

    const static
    #include <iostream>
    class A
    {
    public:
        static const int a = 5;
    };
    // 如果类中初始化了,这里就不能再次初始化了
    //const int A::a = 5;
    
    void main()
    {
        std::cout << A::a << std::endl;
        system("pause");
    }


    ⑥声明类的成员函数

    显而易见的作用

    附录:

    union的成员是特殊的。不能将其成员定义为static。原因?看看union是干什么的吧~

    这些英文术语极其难翻译,干脆直接贴上来。后边有解释。

    static duration:静态生存期,程序创建时即分配此变量的内存,存放在全局静态存储区。程序创建时分配,结束时销毁。具有初始值。

    C++内存分配:静态存储区常量存储区自由存储区

    全局静态存储区:程序创建时分配,结束时销毁。

    常量存储区:不允许修改。程序创建时分配,结束时销毁。

    :局部变量、函数参数等。生存期结束后销毁。空间较小,不过可以手动修改。

    :动态内存分配(new)。编译器不负责回收。

    自由存储区:动态内存分配(malloc)。编译器不负责回收。

    external linkage:可以外部链接的。即其他编译单元(.cpp文件)可以使用此变量。也就是说,如果在两个编译单元中使用了同名的static变量,会出错~

    internal linkage:不能外部链接。

  • 相关阅读:
    [KB] Office序列号移除器
    收音机的记忆
    EnCase v7 正式版预览
    关于Ex01和EnCase 6.19的小道消息
    EnCase V7 正式发布 新特性
    [EnCase v7专题] EX01证据文件获取设置释疑
    智能手机应用取证系列之三:腾讯微博Android手机客户端取证分析
    [EnCase v7] EnCase v7零售版改用CodeMeter加密狗
    Http Server的一个示例
    一个简单的加解密算法
  • 原文地址:https://www.cnblogs.com/SelaSelah/p/2438651.html
Copyright © 2011-2022 走看看