9.2. Static membersΒΆ

It is possible to define classes that have static member functions and variables. Static members are not stored in any instance of a class. In fact, you don't need to ever create a class instance in order to access static members.

Like global variables, static member variables persist as long as the entire program. For global variables refresher, refer to the section Scope.

The static keyword is only used with the declaration of a static member, inside the class definition, but not with the definition of that static member:

class X { static int n; }; // declaration (uses 'static')
int X::n = 1;              // definition (does not use 'static')

An example of a static member:

 1#include <iostream>
 2
 3// a class that counts how many live objects
 4// currently exist
 5class counter {
 6   static int instance_count;   // declaration, but no definition
 7   public:
 8      // increase the count when the counter object is created
 9      counter() {
10         ++instance_count;
11      }
12      // decrease the count when the counter object is destroyed
13      ~counter() {
14         --instance_count;
15      }
16
17      int count() const noexcept {
18         return instance_count;
19      }
20};
21
22// must be defined before use
23int counter::instance_count = 0;    // definition. Now the type is complete
24
25void print(const counter& c) {
26   std::cout << "There are " << c.count()
27             << " counter objects in memory\n";
28}
29
30int main() {
31   counter a;
32   print(a);
33   {
34      counter a; print(a);
35      counter b; print(b);
36      counter c; print(c);
37   }
38   print(a);
39}

We could have written our counter so that we did not need an instance member to determine the count.

 1#include <iostream>
 2
 3// a class that counts how many live objects currently exist
 4class counter {
 5   // declaration and definition
 6   constinit static inline int instance_count = 0;
 7   public:
 8      counter() {
 9         ++instance_count;
10      }
11      ~counter() {
12         --instance_count;
13      }
14
15      // can only access static member data
16      static int count() noexcept {
17        return instance_count;
18      }
19
20};
21
22void print() {
23   std::cout << "There are " << counter::count()
24             << " counter objects in memory\n";
25}
26
27int main() {
28   print();
29   {
30      counter a;
31      print();
32      {
33         counter a; print();
34         counter b; print();
35         counter c; print();
36      }
37      print();
38   }
39   print();
40}

A static member function allows us to get the count even if no instances of a counter class have ever been created.

C++20 Feature

Starting in C++20, our counter can be initialized constinit:

constinit is useful for variables that must be initialized at compile time but are still mutable.


More to Explore