The static keyword and its various uses in C++

后端 未结 9 1599
自闭症患者
自闭症患者 2020-11-22 02:07

The keyword static is one which has several meanings in C++ that I find very confusing and I can never bend my mind around how its actually supposed to work.

相关标签:
9条回答
  • 2020-11-22 02:41

    Static variables are shared between every instance of a class, instead of each class having their own variable.

    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;
    

    Each instance of 'MyClass' has their own 'myVar', but share the same 'myStaticVar'. In fact, you don't even need an instance of MyClass to access 'myStaticVar', and you can access it outside of the class like this:

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

    When used inside a function as a local variable (and not as a class member-variable) the static keyword does something different. It allows you to create a persistent variable, without giving global scope.

    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;
    }
    

    It's a global variable in terms of persistence... but without being global in scope/accessibility.

    You can also have static member functions. Static functions are basically non-member functions, but inside the class name's namespace, and with private access to the class's members.

    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;
    }
    

    When you call a member-function, there's a hidden parameter called 'this', that is a pointer to the instance of the class calling the function. Static member functions don't have that hidden parameter... they are callable without a class instance, but also cannot access non-static member variables of a class, because they don't have a 'this' pointer to work with. They aren't being called on any specific class instance.

    0 讨论(0)
  • 2020-11-22 02:44

    It's actually quite simple. If you declare a variable as static in the scope of a function, its value is preserved between successive calls to that function. So:

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

    will show 678 instead of 666, because it remembers the incremented value.

    As for the static members, they preserve their value across instances of the class. So the following code:

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

    will print 4, because first.a and second.a are essentially the same variable. As for the initialization, see this question.

    0 讨论(0)
  • 2020-11-22 02:47

    When you a declare a static variable at file scope, then that variable is only available in that particular file (technically, the *translation unit, but let's not complicate this too much). For example:

    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;
    }
    

    For a local variable, static means that the variable will be zero-initialized and retain its value between calls:

    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;
    }
    

    For class variables, it means that there is only a single instance of that variable that is shared among all members of that class. Depending on permissions, the variable can be accessed from outside the class using its fully qualified name.

    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;
    };
    

    Marking a non-class function as static makes the function only accessible from that file and inaccessible from other files.

    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;
    }
    

    For class member functions, marking them as static means that the function doesn't need to be called on a particular instance of an object (i.e. it doesn't have a this pointer).

    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;
    }
    
    0 讨论(0)
  • 2020-11-22 02:49

    Static storage duration means that the variable resides in the same place in memory through the lifetime of the program.

    Linkage is orthogonal to this.

    I think this is the most important distinction you can make. Understand this and the rest, as well as remembering it, should come easy (not addressing @Tony directly, but whoever might read this in the future).

    The keyword static can be used to denote internal linkage and static storage, but in essence these are different.

    What does it mean with local variable? Is that a function local variable?

    Yes. Regardless of when the variable is initialized (on first call to the function and when execution path reaches the declaration point), it will reside in the same place in memory for the life of the program. In this case, static gives it static storage.

    Now what about the case with static and file scope? Are all global variables considered to have static storage duration by default?

    Yes, all globals have by definition static storage duration (now that we cleared up what that means). But namespace scoped variables aren't declared with static, because that would give them internal linkage, so a variable per translation unit.

    How does static relate to the linkage of a variable?

    It gives namespace-scoped variables internal linkage. It gives members and local variables static storage duration.

    Let's expand on all this:

    //
    
    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 class instances 
    };
    
    void foo()
    {
       static int x;     //static storage duration - shared between calls
    }
    

    This whole static keyword is downright confusing

    Definitely, unless you're familiar with it. :) Trying to avoid adding new keywords to the language, the committee re-used this one, IMO, to this effect - confusion. It's used to signify different things (might I say, probably opposing things).

    0 讨论(0)
  • 2020-11-22 02:52

    Static Object: We can define class members static using static keyword. When we declare a member of a class as static it means no matter how many objects of the class are created, there is only one copy of the static member.

    A static member is shared by all objects of the class. All static data is initialized to zero when the first object is created, if no other initialization is present. We can't put it in the class definition but it can be initialized outside the class as done in the following example by redeclaring the static variable, using the scope resolution operator :: to identify which class it belongs to.

    Let us try the following example to understand the concept of static data members:

    #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;
    }
    

    When the above code is compiled and executed, it produces the following result:

    Constructor called.
    Constructor called.
    Total objects: 2
    

    Static Function Members: By declaring a function member as static, you make it independent of any particular object of the class. A static member function can be called even if no objects of the class exist and the static functions are accessed using only the class name and the scope resolution operator ::.

    A static member function can only access static data member, other static member functions and any other functions from outside the class.

    Static member functions have a class scope and they do not have access to the this pointer of the class. You could use a static member function to determine whether some objects of the class have been created or not.

    Let us try the following example to understand the concept of static function members:

    #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;
    }
    

    When the above code is compiled and executed, it produces the following result:

    Inital Stage Count: 0
    Constructor called.
    Constructor called.
    Final Stage Count: 2
    
    0 讨论(0)
  • 2020-11-22 02:53

    I'm not a C programmer so I can't give you information on the uses of static in a C program properly, but when it comes to Object Oriented programming static basically declares a variable, or a function or a class to be the same throughout the life of the program. Take for example.

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

    When you instantiate this class in your Main you do something like this.

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

    These two class instances are completely different from each other and operate independently from one another. But if you were to recreate the class A like this.

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

    Lets go back to the main again.

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

    Then a1 and a2 would share the same copy of int x whereby any operations on x in a1 would directly influence the operations of x in a2. So if I was to do this

    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
    }
    

    Both instances of the class A share static variables and functions. Hope this answers your question. My limited knowledge of C allows me to say that defining a function or variable as static means it is only visible to the file that the function or variable is defined as static in. But this would be better answered by a C guy and not me. C++ allows both C and C++ ways of declaring your variables as static because its completely backwards compatible with C.

    0 讨论(0)
提交回复
热议问题