The Static Keyword and Its Various Uses in C++

The static keyword and its various uses in C++

Variables:

static variables exist for the "lifetime" of the translation unit that it's defined in, and:

  • If it's in a namespace scope (i.e. outside of functions and classes), then it can't be accessed from any other translation unit. This is known as "internal linkage" or "static storage duration". (Don't do this in headers except for constexpr. Anything else, and you end up with a separate variable in each translation unit, which is crazy confusing)
  • If it's a variable in a function, it can't be accessed from outside of the function, just like any other local variable. (this is the local they mentioned)
  • class members have no restricted scope due to static, but can be addressed from the class as well as an instance (like std::string::npos). [Note: you can declare static members in a class, but they should usually still be defined in a translation unit (cpp file), and as such, there's only one per class]

locations as code:

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

Before any function in a translation unit is executed (possibly after main began execution), the variables with static storage duration (namespace scope) in that translation unit will be "constant initialized" (to constexpr where possible, or zero otherwise), and then non-locals are "dynamically initialized" properly in the order they are defined in the translation unit (for things like std::string="HI"; that aren't constexpr). Finally, function-local statics will be initialized the first time execution "reaches" the line where they are declared. All static variables all destroyed in the reverse order of initialization.

The easiest way to get all this right is to make all static variables that are not constexpr initialized into function static locals, which makes sure all of your statics/globals are initialized properly when you try to use them no matter what, thus preventing the static initialization order fiasco.

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

Be careful, because when the spec says namespace-scope variables have "static storage duration" by default, they mean the "lifetime of the translation unit" bit, but that does not mean it can't be accessed outside of the file.

Functions

Significantly more straightforward, static is often used as a class member function, and only very rarely used for a free-standing function.

A static member function differs from a regular member function in that it can be called without an instance of a class, and since it has no instance, it cannot access non-static members of the class. Static variables are useful when you want to have a function for a class that definitely absolutely does not refer to any instance members, or for managing static member variables.

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
}

A static free-function means that the function will not be referred to by any other translation unit, and thus the linker can ignore it entirely. This has a small number of purposes:

  • Can be used in a cpp file to guarantee that the function is never used from any other file.
  • Can be put in a header and every file will have it's own copy of the function. Not useful, since inline does pretty much the same thing.
  • Speeds up link time by reducing work
  • Can put a function with the same name in each translation unit, and they can all do different things. For instance, you could put a static void log(const char*) {} in each cpp file, and they could each all log in a different way.

What does static mean in C?

  1. A static variable inside a function keeps its value between invocations.
  2. A static global variable or a function is "seen" only in the file it's declared in

(1) is the more foreign topic if you're a newbie, so here's an example:

#include <stdio.h>

void foo()
{
int a = 10;
static int sa = 10;

a += 5;
sa += 5;

printf("a = %d, sa = %d\n", a, sa);
}


int main()
{
int i;

for (i = 0; i < 10; ++i)
foo();
}

This prints:

a = 15, sa = 15
a = 15, sa = 20
a = 15, sa = 25
a = 15, sa = 30
a = 15, sa = 35
a = 15, sa = 40
a = 15, sa = 45
a = 15, sa = 50
a = 15, sa = 55
a = 15, sa = 60

This is useful for cases where a function needs to keep some state between invocations, and you don't want to use global variables. Beware, however, this feature should be used very sparingly - it makes your code not thread-safe and harder to understand.

(2) Is used widely as an "access control" feature. If you have a .c file implementing some functionality, it usually exposes only a few "public" functions to users. The rest of its functions should be made static, so that the user won't be able to access them. This is encapsulation, a good practice.

Quoting Wikipedia:

In the C programming language, static
is used with global variables and
functions to set their scope to the
containing file. In local variables,
static is used to store the variable
in the statically allocated memory
instead of the automatically allocated
memory. While the language does not
dictate the implementation of either
type of memory, statically allocated
memory is typically reserved in data
segment of the program at compile
time, while the automatically
allocated memory is normally
implemented as a transient call stack.

And to answer your second question, it's not like in C#.

In C++, however, static is also used to define class attributes (shared between all objects of the same class) and methods. In C there are no classes, so this feature is irrelevant.

Why does the static keyword have so many meanings in C and C++? [duplicate]

Adding new keywords to a language breaks backwards compatibility. So static gets used where its use might possibly mean something ( int arr[static 50] vs int arr[auto 50] or int arr[extern 50] ) and cannot syntactically appear in that location based its use in previous versions.

Though in that case adding a not_less_than context sensitive keyword in that position would not break previous code, it would add another keyword (so simple text editors which are keyword aware but not syntax aware would not know whether or not it is a keyword), and break the 'keywords are not context sensitive' simplification made in C.

what's the difference meaning of the keyword static between c and c++?

static is probably the most confusingly overloaded keyword in both C and C++. It means different things in different places.

  • Within functions, static is a storage class, denoting variables which exist for the lifetime of the programme. So saying

    void f() {
    static int i = 0;
    }

    says that the value of i will be preserved between calls to f(). Other storage classes are the default auto (but beware the change in meaning in C++11), extern, and register, plus thread_local in C11/C++11.

  • At file scope (or namespace scope in C++), static is a linkage specifier. Functions and variables marked static in this way have internal linkage, and so are local to the current translation unit. What this means is that a function like

     static int f() {
    return 3;
    }

    can only be referenced by other functions inside the same .c file. This usage of static was deprecated in C++03 in favour of unnamed namespaces. I read somewhere it was undeprecated again in C++11.

  • In C++, when applied to a member function or member variable of a class, it means that the function or variable does not need a class instance in order to be accessed. There is little different between "class static" member functions/variables and global functions/variable in terms of implementation, except that C++ class access specifiers apply to members.

  • One last one: in C99 (but not C++), static can be used within an array function parameter, like so:

    void f(int a[static 4]) {
    }

    this specifies that the parameter a must by an integer array of size at least 4.

I think that's all of them, but let me know in the comments if there are any I've forgotten!

when/why should i use static in c++?

static has a couple of independent meanings, depending on context.

void f() { ... }
static void g() { ... }

Here, f has "external linkage", which means that its name is visible in other translation units. That is, in another source file you could have void f(); and then you could call the function f.

g, on the other hand, because it's marked static, has "internal linkage". You can call it from code in the same source file, but you cannot call it from another source file.

Same for objects:

int i = 3;        // external linkage
static int j = 4; // internal linkage

And a small complication: you can define a static object inside a function.

void f() {
static int i = 3;
std::cout << i << '\n';
++i;
}

Here, i has no linkage. It's only visible inside the function. It gets initialized the first time the function is called (and doesn't get initialized at all if the function isn't called). So the first time that f is called it will write "3" to the console. On the second call it will write "4", etc. Understanding the behavior of objects with destructors is left as an exercise for the reader.

Inside a class definition it's completely different.

class C {
public:
void f();
static void g();
int i;
static int j;
};

Here, when you call f you must call it on an object of type C, and f can use data members of that object, that is, it can look at and change both i and j. When you call g there is no associated object. It's still a member of C, so it can look at and change j, because j, too, is not associated with any object. There's only one j, and it's shared by all objects of type C.

Why don't we have to declare static functions the same way we need to declare static variables in c++?

Static member functions are ordinary functions at the assembly level. The difference is only the hidden pointer 'this' that does not exist in them. They are basically global functions that exist like any other non static or non member (and not inline) function within the C++scope of a class name. Function scopes are C++ thing, they are not there at the CPU level.

Static variables are different. They exist before any class object is created. They are not created when a class instance is created. They are there as globals.

Perhaps it's done the way it's done to emphasize that difference.



Related Topics



Leave a reply



Submit