首页 文章

static关键字及其在C中的各种用途

提问于
浏览
164

关键字 static 是一个在C中具有多种含义的关键词,我觉得很困惑,而且我永远无法理解它实际上应该如何工作 .

根据我的理解,存储持续时间为 static ,这意味着它在全局的情况下持续程序的生命周期,但是默认情况下初始化为零时为're talking about a local, it means that it' .

C标准为具有关键字 static 的类数据成员说明了这一点:

3.7.1 Static storage duration [basic.stc.static]

3关键字static可用于声明具有静态存储持续时间的局部变量 . 4应用于类定义中的类数据成员的关键字static为数据成员提供静态存储持续时间 .

局部变量是什么意思?这是一个函数局部变量吗?因为还有一个当你声明一个本地函数 static 时它只被初始化一次,它第一次进入这个函数 .

它还只讨论了关于类成员的存储持续时间,它是非实例特定的,这也是 static 不是的属性?或者是存储持续时间?

那么 static 和文件范围的情况呢?是否所有全局变量都被视为默认具有静态存储持续时间?以下(来自第3.7.1节)似乎表明:

1所有没有动态存储持续时间,没有线程存储持续时间且不是本地的变量都具有静态存储持续时间 . 这些实体的存储应持续该计划的持续时间(3.6.2,3.6.3)

static 如何与变量的链接相关?

整个 static 关键字是彻头彻尾的混乱,有人可以澄清英语的不同用途,并告诉我何时初始化 static 类成员?

9 回答

  • 19

    变量:

    static 变量存在于其定义的翻译单元的"lifetime"中,并且:

    • 如果从任何其他翻译单元访问's in a namespace scope (i.e. outside of functions and classes), then it can' . 这被称为"internal linkage"或"static storage duration" . (不要' do this in headers, it'只是一个可怕的想法,你最终在每个翻译单元中都有一个单独的变量,这是一个疯狂的混乱)

    • 如果它是函数中的变量,则无法从函数外部访问它,就像任何其他局部变量一样 . (这是他们提到的当地人)
      由于 static

    • 类成员没有限制范围,但可以从类和实例(如 std::string::npos )进行寻址 . [注意:您可以在类中声明静态成员,但它们通常仍应在翻译单元(cpp文件)中定义,因此,每个类只有一个]

    位置代码:

    static std::string namespaceScope = "Hello";
    void foo() {
        static std::string functionScope= "World";
    }
    struct A {
       static std::string classScope = "!";
    };
    

    在执行翻译单元中的任何功能之前(可能在 main 开始执行之后),该翻译单元中具有静态存储持续时间(命名空间范围)的变量将是"constant initialized"(在可能的情况下为 constexpr ,否则为零),然后是非本地的是"dynamically initialized"正确按照它们在翻译单元中定义的顺序(对于像 std::string="HI"; 这样不是 constexpr 的东西) . 最后,函数本地静态将在第一次执行时被初始化"reaches"它们被声明的行 . 所有 static 变量都以与初始化相反的顺序销毁 .

    实现所有这一切的最简单方法是将所有非 constexpr 初始化的静态变量初始化为函数静态局部变量,这样可以确保在尝试使用它们时正确初始化所有静态/全局变量,从而阻止了static initialization order fiasco .

    T& get_global() {
        static T global = initial_value();
        return global;
    }
    

    要小心,因为当规范说命名空间范围变量默认为"static storage duration"时,它们意味着"lifetime of the translation unit"位,但这并不意味着它不能在文件外部访问 .

    功能

    显而易见, static 经常被用作类成员函数,并且很少用于独立函数 .

    静态成员函数与常规成员函数的不同之处在于,它可以在没有类实例的情况下调用,并且由于它没有实例,因此它无法访问类的非静态成员 . 当你想要一个绝对不会引用任何实例成员的类的函数或管理 static 成员变量时,静态变量很有用 .

    struct A {
        A() {++A_count;}
        A(const A&) {++A_count;}
        A(A&&) {++A_count;}
        ~A() {--A_count;}
    
        static int get_count() {return A_count;}
    private:
        static int A_count;
    }
    
    int main() {
        A var;
    
        int c0 = var.get_count(); //some compilers give a warning, but it's ok.
        int c1 = A::get_count(); //normal way
    }
    

    static 自由函数意味着该函数不会被任何其他转换单元引用,因此链接器可以忽略它完全 . 这有几个目的:

    • 可以在cpp文件中使用,以保证该函数永远不会从任何其他文件中使用 .

    • 可以放在 Headers 中,每个文件都有自己的函数副本 . 没用,因为内联几乎完全相同 .

    • 通过减少工作来加快链接时间

    • 可以在每个翻译单元中放置一个具有相同名称的函数,它们都可以做不同的事情 . 例如,您可以在每个cpp文件中放置一个 static void log(const char*) {} ,它们都可以以不同的方式登录 .

  • 8

    静态存储持续时间意味着变量在程序的生命周期内驻留在内存中的相同位置 .

    链接与此正交 .

    I think this is the most important distinction you can make. 理解这一点,其余的,以及记住它,应该变得容易(不是直接解决@Tony,而是将来可能会读到这个的人) .

    关键字 static 可用于表示内部链接 and 静态存储,但实质上这些是不同的 .

    局部变量是什么意思?这是一个函数局部变量吗?

    是 . 无论何时初始化变量(在第一次调用函数时以及执行路径到达声明点时),它都将在程序的生命周期内驻留在内存中的相同位置 . 在这种情况下, static 为其提供静态存储 .

    现在静态和文件范围的情况怎么样?是否所有全局变量都被视为默认具有静态存储持续时间?

    是的,根据定义,所有全局变量都具有静态存储持续时间(现在我们已经清除了这意味着什么) . But 命名空间作用域变量未使用 static 声明,因为这会给它们内部链接,因此每个转换单元都有一个变量 .

    静态如何与变量的链接相关?

    它为命名空间范围的变量提供内部链接 . 它为成员和局部变量提供静态存储持续时间 .

    让我们扩展所有这些:

    //
    
    static int x; //internal linkage
                  //non-static storage - each translation unit will have its own copy of x
                  //NOT A TRUE GLOBAL!
    
    int y;        //static storage duration (can be used with extern)
                  //actual global
                  //external linkage
    struct X
    {
       static int x;     //static storage duration - shared between classes
    };
    
    void foo()
    {
       static int x;     //static storage duration - shared between calls
    }
    

    这整个静态关键字完全令人困惑

    当然,除非你熟悉它 . :)试图避免在语言中添加新的关键词,委员会重新使用了这个,IMO,这种效果 - 混乱 . 它用来表示不同的东西(可能我会说,可能是反对的东西) .

  • 1

    它实际上非常简单 . 如果在函数范围内将变量声明为static,则在对该函数的连续调用之间保留其值 . 所以:

    int myFun()
    {
    static int i=5;
    i++;
    return i;
    }
    int main()
    {
    printf("%d", myFun());
    printf("%d", myFun());
    printf("%d", myFun());
    }
    

    将显示 678 而不是 666 ,因为它会记住递增的值 .

    至于静态成员,它们在类的实例中保留它们的值 . 所以下面的代码:

    struct A
    {
    static int a;
    };
    int main()
    {
    A first;
    A second;
    first.a = 3;
    second.a = 4;
    printf("%d", first.a);
    }
    

    将打印4,因为first.a和second.a基本上是相同的变量 . 至于初始化,请参阅this question.

  • 1

    为了澄清这个问题,我宁愿用三种不同的形式对'static'关键字的用法进行分类:

    (A). variables

    (B). functions

    (C). member variables/functions of classes

    每个小 Headers 的解释如下:

    (A) 'static' keyword for variables

    这个可能有点棘手,但如果解释和理解得当,它非常简单 .

    为了解释这一点,首先了解变量的 scope, duration and linkage 非常有用,没有这些变量总是难以通过staic关键字的模糊概念看到

    1. Scope :确定文件中的哪个位置可以访问该变量 . 它可以有两种类型:(i) Local or Block Scope . (ii) Global Scope

    2. Duration :确定何时创建和销毁变量 . 同样,它有两种类型:(i) Automatic Storage Duration (对于具有Local或Block范围的变量) . (ii) Static Storage Duration (对于具有全局范围或局部变量的变量(在函数或代码块中)和静态说明符) .

    3. Linkage :确定是否可以在另一个文件中访问(或链接)变量 . 再次(幸运的是)它有两种类型:(i) Internal Linkage (对于具有块范围和全局范围/文件范围/全局命名空间范围的变量)(ii) External Linkage (对于仅具有全局范围/文件范围/全局命名空间的变量)范围)

    让我们参考下面的例子来更好地理解普通的全局和局部变量(没有静态存储持续时间的局部变量):

    //main file
    #include <iostream>
    
    int global_var1; //has global scope
    const global_var2(1.618); //has global scope
    
    int main()
    {
    //these variables are local to the block main.
    //they have automatic duration, i.e, they are created when the main() is 
    //  executed and destroyed, when main goes out of scope
     int local_var1(23);
     const double local_var2(3.14);
    
     {
    /* this is yet another block, all variables declared within this block are 
     have local scope limited within this block. */
    // all variables declared within this block too have automatic duration, i.e, 
    /*they are created at the point of definition within this block,
     and destroyed as soon as this block ends */
       char block_char1;
       int local_var1(32) //NOTE: this has been re-declared within the block, 
    //it shadows the local_var1 declared outside
    
     std::cout << local_var1 <<"\n"; //prints 32
    
      }//end of block
      //local_var1 declared inside goes out of scope
    
     std::cout << local_var1 << "\n"; //prints 23
    
     global_var1 = 29; //global_var1 has been declared outside main (global scope)
     std::cout << global_var1 << "\n"; //prints 29
     std::cout << global_var2 << "\n"; //prints 1.618
    
     return 0;
    }  //local_var1, local_var2 go out of scope as main ends
    //global_var1, global_var2 go out of scope as the program terminates 
    //(in this case program ends with end of main, so both local and global
    //variable go out of scope together
    

    现在出现了Linkage的概念 . 当在一个文件中定义的全局变量打算在另一个文件中使用时,变量的链接起着重要作用 .

    全局变量的链接由关键字指定:(i) static ,和(ii) extern

    (现在你得到解释;-))

    static关键字可以应用于具有本地和全局范围的变量,在这两种情况下,它们意味着不同的东西 . 我将首先解释在具有全局范围的变量中使用'static'关键字(其中我还阐明了关键字'extern'的用法),然后解释了具有局部范围的变量 .

    1. Static Keyword for variables with global scope

    全局变量具有静态持续时间,这意味着当使用它的特定代码块(例如main())结束时,它们不会超出范围 . 根据链接,它们只能在声明它们的同一文件中访问(对于静态全局变量),或者在文件外部甚至在声明它们的文件之外(外部类型全局变量)访问它们 .

    在具有extern说明符的全局变量的情况下,并且如果在初始化它的文件之外访问该变量,则必须在正在使用它的文件中向前声明它,就像函数必须是向前的一样 . 声明它的定义是否在与使用它的位置不同的文件中 .

    相反,如果全局变量具有static关键字,则不能在已声明它的文件之外使用它 .

    (见下面的例子澄清)

    例如:

    //main2.cpp
     static int global_var3 = 23;  /*static global variable, cannot be                            
                                    accessed in anyother file */
     extern double global_var4 = 71; /*can be accessed outside this file                  linked to main2.cpp */
     int main() { return 0; }
    

    main3.cpp

    //main3.cpp
    #include <iostream>
    
    int main()
    {
       extern int gloabl_var4; /*this variable refers to the gloabal_var4
                                defined in the main2.cpp file */
      std::cout << global_var4 << "\n"; //prints 71;
    
      return 0;
    }
    

    现在c中的任何变量都可以是const或非const,对于每个'const-ness',我们得到两个默认c链接的情况,如果没有指定:

    (i) If a global variable is non-const, its linkage is extern by default ,即非const全局变量可以通过使用extern关键字的前向声明在另一个.cpp文件中访问(换句话说,非const全局变量具有外部链接(当然具有静态持续时间)) . 在原始文件中使用extern关键字也是多余的 . 在这种情况下 to make a non-const global variable inaccessible to external file, use the specifier 'static' before the type of the variable .

    (ii) If a global variable is const, its linkage is static by default ,即const全局变量不能在除定义之外的文件中访问(换句话说,const全局变量具有内部链接(当然具有静态持续时间)) . 还使用static关键字来防止在另一个文件中访问const全局变量是多余的 . 在这里, to make a const global variable have an external linkage, use the specifier 'extern' before the type of the variable

    以下是具有各种链接的全局范围变量的摘要

    //globalVariables1.cpp 
    
    // defining uninitialized vairbles
    int globalVar1; //  uninitialized global variable with external linkage 
    static int globalVar2; // uninitialized global variable with internal linkage
    const int globalVar3; // error, since const variables must be initialized upon declaration
    const int globalVar4 = 23; //correct, but with static linkage (cannot be accessed outside the file where it has been declared*/
    extern const double globalVar5 = 1.57; //this const variable ca be accessed outside the file where it has been declared
    

    接下来,我们将研究在不同文件中访问时上述全局变量的行为方式 .

    //using_globalVariables1.cpp (eg for the usage of global variables above)
    
    // Forward declaration via extern keyword:
     extern int globalVar1; // correct since globalVar1 is not a const or static
     extern int globalVar2; //incorrect since globalVar2 has internal linkage
     extern const int globalVar4; /* incorrect since globalVar4 has no extern 
                             specifier, limited to internal linkage by
                             default (static specifier for const variables) */
     extern const double globalVar5; /*correct since in the previous file, it 
                               has extern specifier, no need to initialize the
                           const variable here, since it has already been
                           legitimately defined perviously */
    

    2. Static Keyword for variables with Local Scope

    之前我提到过具有局部范围的变量具有自动持续时间,即它们在输入块时存在(无论是普通块,还是功能块),当块结束时不再存在,长话短说, variables with local scope have automatic duration 和自动持续时间变量(和对象)没有链接意味着它们在代码块之外是不可见的 .

    如果 static 说明符应用于块中的局部变量,则 changes the duration of the variable from automatic to static 及其生命周期是程序的整个持续时间,这意味着它具有固定的内存位置,并且其值仅在程序启动之前初始化一次,如cpp reference中所述 . (初始化不应与赋值混淆)

    让我们来看一个例子 .

    //localVarDemo.cpp
     #include <iostream>
    
     int localNextID()
    {
      int tempID = 1;  //tempID created here
      return tempID++; //copy of tempID returned and tempID incremented to 2
    } //tempID destroyed here, hence value of tempID lost
    
    int newNextID()
    {
      static int newID = 0;//newID has static duration, with internal linkage
      return newID++; //copy of newID returned and newID incremented by 1
    }  //newID doesn't get destroyed here :-)
    
    
    int main()
    {
      int employeeID1 = nextID();  //employeeID1 = 1
      int employeeID2 = nextID();  // employeeID2 = 1 again (not desired)
      int employeeID3 = newNextID(); //employeeID3 = 0;
      int employeeID4 = newNextID(); //employeeID4 = 1;
      int employeeID5 = newNextID(); //employeeID5 = 2;
      return 0;
    }
    

    以上是对应用于变量的static关键字的解释 . pheww!

    B. 'static' keyword used for functions

    在函数方面,static关键字具有直接的含义 . 这里, refers to linkage of the function 通常,在cpp文件中声明的所有函数都默认具有外部链接,即在一个文件中定义的函数可以通过前向声明在另一个cpp文件中使用 .

    using a static keyword before the function declaration limits its linkage to internal ,即静态函数不能在其定义之外的文件中使用 .

    C. Staitc Keyword used for member variables and functions of classes

    1. 'static' keyword for member variables of classes

    我在这里直接开始一个例子

    #include <iostream>
    
    class DesignNumber
    {
      private:
    
          static int m_designNum;  //design number
          int m_iteration;     // number of iterations performed for the design
    
      public:
        DesignNumber() {     }  //default constructor
    
       int  getItrNum() //get the iteration number of design
       {
          m_iteration = m_designNum++;
          return m_iteration;
       }
         static int m_anyNumber;  //public static variable
    };
    int DesignNumber::m_designNum = 0; // starting with design id = 0
                         // note : no need of static keyword here
                         //causes compiler error if static keyword used
    int DesignNumber::m_anyNumber = 99; /* initialization of inclass public 
                                        static member  */
    enter code here
    
    int main()
    {
       DesignNumber firstDesign, secondDesign, thirdDesign;
       std::cout << firstDesign.getItrNum() << "\n";  //prints 0
       std::cout << secondDesign.getItrNum() << "\n"; //prints 1
       std::cout << thirdDesign.getItrNum() << "\n";  //prints 2
    
       std::cout << DesignNumber::m_anyNumber++ << "\n";  /* no object
                                            associated with m_anyNumber */
       std::cout << DesignNumber::m_anyNumber++ << "\n"; //prints 100
       std::cout << DesignNumber::m_anyNumber++ << "\n"; //prints 101
    
       return 0;
    }
    

    在此示例中,静态变量m_designNum保留其值,并且此单个私有成员变量(因为它是静态的)与对象类型DesignNumber的所有变量共享b / w

    与其他成员变量一样,类的静态成员变量也不与任何类对象相关联,这可以通过在main函数中打印anyNumber来演示

    const vs non-const static member variables in class

    (i) non-const class static member variables 在前面的示例中,静态成员(公共和私有)都是非常量 . ISO标准禁止在类中初始化非常量静态成员 . 因此,与前面的示例一样,它们必须在类定义之后初始化,并且需要忽略static关键字

    (ii) const-static member variables of class 这很简单,并且符合其他const成员变量初始化的约定,即类的const静态成员变量可以在声明点初始化,它们可以是在类声明结束时初始化,但有一点需要注意,在类定义之后初始化时,需要将关键字const添加到静态成员中 .

    但是,我建议在声明点初始化const静态成员变量 . 这符合标准的C约定,使代码看起来更清晰

    有关类中静态成员变量的更多示例,请从learncpp.com查看以下链接http://www.learncpp.com/cpp-tutorial/811-static-member-variables/

    2. 'static' keyword for member function of classes

    就像类的成员变量可以是静态的一样,类的成员函数也是如此 . 类的普通成员函数始终与类类型的对象相关联 . 相反,类的静态成员函数不与类的任何对象相关联,即它们没有* this指针 .

    其次,因为类的静态成员函数没有* this指针,所以可以使用main函数中的类名和范围解析运算符来调用它们(ClassName :: functionName();)

    第三,类的静态成员函数只能访问类的静态成员变量,因为类的非静态成员变量必须属于类对象 .

    有关类中静态成员函数的更多示例,请从learncpp.com查找以下链接

    http://www.learncpp.com/cpp-tutorial/812-static-member-functions/

  • 1

    静态变量在类的每个实例之间共享,而不是每个类都有自己的变量 .

    class MyClass
    {
        public:
        int myVar; 
        static int myStaticVar;
    };
    
    //Static member variables must be initialized. Unless you're using C++11, or it's an integer type,
    //they have to be defined and initialized outside of the class like this:
    MyClass::myStaticVar = 0;
    
    MyClass classA;
    MyClass classB;
    

    'MyClass'的每个实例都有自己的'myVar',但共享相同的'myStaticVar' . 实际上,您甚至不需要MyClass的实例来访问“myStaticVar”,您可以在类之外访问它,如下所示:

    MyClass::myStaticVar //Assuming it's publicly accessible.
    

    当在函数内部用作局部变量(而不是作为类成员变量)时,static关键字会做出不同的事情 . 它允许您创建持久变量,而不提供全局范围 .

    int myFunc()
    {
       int myVar = 0; //Each time the code reaches here, a new variable called 'myVar' is initialized.
       myVar++;
    
       //Given the above code, this will *always* print '1'.
       std::cout << myVar << std::endl;
    
       //The first time the code reaches here, 'myStaticVar' is initialized. But ONLY the first time.
       static int myStaticVar = 0;
    
       //Each time the code reaches here, myStaticVar is incremented.
       myStaticVar++;
    
       //This will print a continuously incrementing number,
       //each time the function is called. '1', '2', '3', etc...
       std::cout << myStaticVar << std::endl;
    }
    

    就持久性而言,它是一个全局变量......但没有全局范围/可访问性 .

    您还可以拥有静态成员函数 . 静态函数基本上是非成员函数,但在类名的命名空间内,并且具有对类成员的私有访问权 .

    class MyClass
    {
        public:
        int Func()
        {
            //...do something...
        }
    
        static int StaticFunc()
        {
            //...do something...
        }
    };
    
    int main()
    {
       MyClass myClassA;
       myClassA.Func(); //Calls 'Func'.
       myClassA.StaticFunc(); //Calls 'StaticFunc'.
    
       MyClass::StaticFunc(); //Calls 'StaticFunc'.
       MyClass::Func(); //Error: You can't call a non-static member-function without a class instance!
    
       return 0;
    }
    

    当你调用一个成员函数时,有's a hidden parameter called ' this',这是一个指向调用该函数的类实例的指针 . 静态成员函数 don't 具有该隐藏参数...它们可以在没有类实例的情况下调用,但也无法访问类的非静态成员变量,因为它们在任何特定的类实例上都不会被调用' pointer to work with. They aren' .

  • 116

    当您在文件范围声明 static 变量时,该变量仅在该特定文件中可用(从技术上讲,*转换单元,但不要让它太复杂) . 例如:

    a.cpp

    static int x = 7;
    
    void printax()
    {
        cout << "from a.cpp: x=" << x << endl;
    }
    

    b.cpp

    static int x = 9;
    
    void printbx()
    {
        cout << "from b.cpp: x=" << x << endl;
    }
    

    main.cpp:

    int main(int, char **)
    {
        printax(); // Will print 7
        printbx(); // Will print 9
    
        return 0;
    }
    

    对于局部变量, static 表示该变量将被零初始化并在调用之间保留其值:

    unsigned int powersoftwo()
    {
        static unsigned lastpow;
    
        if(lastpow == 0)
            lastpow = 1;
        else
            lastpow *= 2;
    
        return lastpow;
    }
    
    int main(int, char **)
    {
        for(int i = 0; i != 10; i++)
            cout << "2^" << i << " = " << powersoftwo() << endl;
    }
    

    对于类变量,它意味着该类的所有成员之间只共享该变量的单个实例 . 根据权限,可以使用其完全限定名称从类外部访问该变量 .

    class Test
    {
    private:
        static char *xxx;
    
    public:
        static int yyy;
    
    public:
        Test()
        {        
            cout << this << "The static class variable xxx is at address "
                 << static_cast<void *>(xxx) << endl;
            cout << this << "The static class variable yyy is at address "
                 << static_cast<void *>(&y) << endl;
        }
    };
    
    // Necessary for static class variables.
    char *Test::xxx = "I'm Triple X!";
    int Test::yyy = 0;
    
    int main(int, char **)
    {
        Test t1;
        Test t2;
    
        Test::yyy = 666;
    
        Test t3;
    };
    

    将非类函数标记为 static 使得该函数只能从该文件访问,并且无法从其他文件访问 .

    a.cpp

    static void printfilename()
    { // this is the printfilename from a.cpp - 
      // it can't be accessed from any other file
        cout << "this is a.cpp" << endl;
    }
    

    b.cpp

    static void printfilename()
    { // this is the printfilename from b.cpp - 
      // it can't be accessed from any other file
        cout << "this is b.cpp" << endl;
    }
    

    对于类成员函数,将它们标记为 static 意味着该函数不具有 this 指针 .

    class Test
    {
    private:
        static int count;
    
    public:
        static int GetTestCount()
        {
            return count;
        };
    
        Test()
        {
            cout << this << "Created an instance of Test" << endl;
            count++;
        }
    
        ~Test()
        {
            cout << this << "Destroyed an instance of Test" << endl;
            count--;
        }
    };
    
    int Test::count = 0;
    
    int main(int, char **)
    {
        Test *arr[10] = { NULL };
    
        for(int i = 0; i != 10; i++)
            arr[i] = new Test();
    
        cout << "There are " << Test::GetTestCount() << " instances of the Test class!" << endl;
    
        // now, delete them all except the first and last!
        for(int i = 1; i != 9; i++)
            delete arr[i];        
    
        cout << "There are " << Test::GetTestCount() << " instances of the Test class!" << endl;
    
        delete arr[0];
    
        cout << "There are " << Test::GetTestCount() << " instances of the Test class!" << endl;
    
        delete arr[9];
    
        cout << "There are " << Test::GetTestCount() << " instances of the Test class!" << endl;
    
        return 0;
    }
    
  • 7

    我不是C程序员,因此我无法正确地向您提供有关静态在C程序中使用的信息,但是当面向对象编程时,静态基本上声明一个变量,或者一个函数或类是相同的整个计划的整个生命周期 . 举个例子 .

    class A
    {
    public:
        A();
        ~A();
        void somePublicMethod();
    private:
        void somePrivateMethod();
    };
    

    当你在Main中实例化这个类时,你会做这样的事情 .

    int main()
    {
       A a1;
       //do something on a1
       A a2;
       //do something on a2
    }
    

    这两个类实例彼此完全不同,并且彼此独立地操作 . 但是如果你要重新创建这样的A类 .

    class A
    {
    public:
        A();
        ~A();
        void somePublicMethod();
        static int x;
    private:
        void somePrivateMethod();
    };
    

    让我们再回到主要 .

    int main()
    {
       A a1;
       a1.x = 1;
       //do something on a1
       A a2;
       a2.x++;
       //do something on a2
    }
    

    然后a1和a2将共享相同的int x副本,其中a1中x上的任何操作都将直接影响a2中x的操作 . 所以如果我这样做的话

    int main()
    {
       A a1;
       a1.x = 1;
       //do something on a1
       cout << a1.x << endl; //this would be 1
       A a2;
       a2.x++;
       cout << a2.x << endl; //this would be 2 
       //do something on a2
    }
    

    A类的两个实例共享静态变量和函数 . 希望这能回答你的问题 . 我对C的有限知识允许我说将函数或变量定义为static意味着它只对文件可见,函数或变量被定义为静态 . 但是这样可以更好地回答一个C人而不是我 . C允许C和C两种方式将变量声明为静态,因为它完全向后兼容C.

  • 17

    局部变量是什么意思?这是一个函数局部变量吗?

    是 - 非全局,例如函数局部变量 .

    因为当你将一个本地函数声明为静态时,它只被初始化一次,它第一次进入这个函数 .

    对 .

    它还只谈到关于类成员的存储持续时间,它是非实例特定的,那也是静态的属性?或者是存储持续时间?

    class R { static int a; }; // << static lives for the duration of the program
    

    也就是说,永远不会复制 R share int R::a - int R::a 的所有实例 .

    现在静态和文件范围的情况怎么样?

    实际上是一个具有构造函数/析构函数的全局 - 初始化在访问之前不会延迟 .

    静态如何与变量的链接相关?

    对于本地函数,它是外部的 . 访问:该功能可访问(当然,除非您将其返回) .

    对于一个类,它是外部的 . 访问:标准访问说明符适用(公共,受保护,私有) .

    static 还可以指定内部链接,具体取决于它的声明位置(文件/命名空间) .

    这整个静态关键字完全令人困惑

    它在C中有太多用途 .

    有人可以澄清英语的不同用法,并告诉我何时初始化静态类成员?

    它会在 main 之前自动初始化,如果's loaded and has a constructor. That might sound like a good thing, but initialization order is largely beyond your control, so complex initialization becomes very difficult to maintain, and you want to minimize this -- if you must have a static, then function local scales much better across libraries and projects. As far as data with static storage duration, you should try to minimize this design, particularly if mutable (global variables). Initialization ' time'也因多种原因而变化 - 加载器和内核有一些技巧可以最小化内存占用并推迟初始化,具体取决于相关数据 .

  • 57

    Static Object: 我们可以使用static关键字定义类成员static . 当我们将类的成员声明为static时,意味着无论创建了多少个类的对象,都只有一个静态成员的副本 .

    静态成员由类的所有对象共享 . 如果没有其他初始化,则在创建第一个对象时,所有静态数据都将初始化为零 . 我们不能将它放在类定义中,但它可以在类外部初始化,如下例所示,通过重新声明静态变量,使用范围解析运算符::来标识它所属的类 .

    让我们尝试以下示例来理解静态数据成员的概念:

    #include <iostream>
    
    using namespace std;
    
    class Box
    {
       public:
          static int objectCount;
          // Constructor definition
          Box(double l=2.0, double b=2.0, double h=2.0)
          {
             cout <<"Constructor called." << endl;
             length = l;
             breadth = b;
             height = h;
             // Increase every time object is created
             objectCount++;
          }
          double Volume()
          {
             return length * breadth * height;
          }
       private:
          double length;     // Length of a box
          double breadth;    // Breadth of a box
          double height;     // Height of a box
    };
    
    // Initialize static member of class Box
    int Box::objectCount = 0;
    
    int main(void)
    {
       Box Box1(3.3, 1.2, 1.5);    // Declare box1
       Box Box2(8.5, 6.0, 2.0);    // Declare box2
    
       // Print total number of objects.
       cout << "Total objects: " << Box::objectCount << endl;
    
       return 0;
    }
    

    编译并执行上述代码时,会产生以下结果:

    Constructor called.
    Constructor called.
    Total objects: 2
    

    Static Function Members: 通过将函数成员声明为static,可以使其独立于类的任何特定对象 . 即使没有类的对象存在,也可以调用静态成员函数,并且仅使用类名和范围解析运算符::来访问静态函数 .

    静态成员函数只能访问静态数据成员,其他静态成员函数以及类外部的任何其他函数 .

    静态成员函数具有类作用域,并且它们无权访问该类的this指针 . 您可以使用静态成员函数来确定是否已创建类的某些对象 .

    让我们尝试以下示例来理解静态函数成员的概念:

    #include <iostream>
    
    using namespace std;
    
    class Box
    {
       public:
          static int objectCount;
          // Constructor definition
          Box(double l=2.0, double b=2.0, double h=2.0)
          {
             cout <<"Constructor called." << endl;
             length = l;
             breadth = b;
             height = h;
             // Increase every time object is created
             objectCount++;
          }
          double Volume()
          {
             return length * breadth * height;
          }
          static int getCount()
          {
             return objectCount;
          }
       private:
          double length;     // Length of a box
          double breadth;    // Breadth of a box
          double height;     // Height of a box
    };
    
    // Initialize static member of class Box
    int Box::objectCount = 0;
    
    int main(void)
    {
    
       // Print total number of objects before creating object.
       cout << "Inital Stage Count: " << Box::getCount() << endl;
    
       Box Box1(3.3, 1.2, 1.5);    // Declare box1
       Box Box2(8.5, 6.0, 2.0);    // Declare box2
    
       // Print total number of objects after creating object.
       cout << "Final Stage Count: " << Box::getCount() << endl;
    
       return 0;
    }
    

    编译并执行上述代码时,会产生以下结果:

    Inital Stage Count: 0
    Constructor called.
    Constructor called.
    Final Stage Count: 2
    

相关问题