29

In the class:

class foo
{
public:
    static int bar; //declaration of static data member
};

int foo::bar = 0; //definition of data member

We have to explicitly define the static variable, otherwise it will result in a

undefined reference to 'foo::bar'

My question is:

Why do we have to give an explicit definition of a static variable?


Please note that this is NOT a duplicate of previously asked undefined reference to static variable questions. This question intends to ask the reason behind explicit definition of a static variable.

Community
  • 1
  • 1
shauryachats
  • 9,975
  • 4
  • 35
  • 48
  • 6
    If this class is in a header that is compiled with three separate translation units, how do you ensure that the ODR isn't violated unless only one translation unit has the definition, outside of the header? – chris Mar 24 '15 at 02:28
  • 1
    Some (read: exactly one) compiling unit needs to contain the reference to `foo::bar`. – Kijewski Mar 24 '15 at 02:28
  • @chris I'm sorry, I did not understand what you said. Could you please expand on that? What is ODR? – shauryachats Mar 24 '15 at 02:31
  • 2
    @volerag, It's pretty much just based on the [One Definition Rule](http://en.wikipedia.org/wiki/One_Definition_Rule). You can think of a translation unit as one .cpp file that you compile along with every recursively included header file "pasted" into the top of that .cpp file. Things defined in headers are bound to be defined more than once when you start combining the translation units unless they are allowed to be (like class definitions) or special care is taken (like the variable in question here). – chris Mar 24 '15 at 02:34
  • @chris Thanks for explaining ODR. So, I can conclude that static variables have to explicitly declared only one to help it follow the One Definition Rule? Please correct me if I'm wrong. – shauryachats Mar 24 '15 at 02:39
  • 3
    This gets more interesting with C++11 which allows in class initialization and so in many cases you don't need an external definition unless it is odr used but figuring out when something is odr-used can be [very tricky in many cases](http://stackoverflow.com/q/8016780/1708801). – Shafik Yaghmour Mar 24 '15 at 02:40
  • @volerag, s/declared/defined, but yes. Obviously, languages like C# don't need you to do this, but I haven't sat down and thought about what actually goes on enough to see at what point C++ could do the same. – chris Mar 24 '15 at 02:45
  • 1
    con't and then you see some really wacky cases like this [one from the draft C++14 standard](http://stackoverflow.com/q/28506342/1708801). – Shafik Yaghmour Mar 24 '15 at 02:55
  • 1
    While the laws, rules and mechanics around all of this is excellently explained in the comments here and in AnT's full answer, I think it's important to note that compilers today support non-standard attributes that allows the rules to be bypassed, specifically with [`__declspec(selectany)`](http://stackoverflow.com/a/186042/6345) – Johann Gerell Mar 24 '15 at 09:02
  • That's a useful information to have. Thanks @JohannGerell :) – shauryachats Mar 24 '15 at 09:20
  • @JohannGerell beware non-standard compiler optimizations, speaking of `__declspec(selectany) ` see [Is Visual Studio 2013 optimizing correctly in the presence of /OPT:ICF?](http://stackoverflow.com/q/29056890/1708801) for non-conforming behavior related to this feature and optimizations around it. – Shafik Yaghmour Mar 24 '15 at 15:02
  • 1
    also had this question in mind – lakshya_arora Apr 10 '15 at 18:31
  • Possible duplicate of [Why does a static data member need to be defined outside of the class?](https://stackoverflow.com/questions/18749071/why-does-a-static-data-member-need-to-be-defined-outside-of-the-class) – Swapnil Dec 09 '17 at 07:11

5 Answers5

30

From the beginning of time C++ language, just like C, was built on the principle of independent translation. Each translation unit is compiled by the compiler proper independently, without any knowledge of other translation units. The whole program only comes together later, at linking stage. Linking stage is the earliest stage at which the entire program is seen by linker (it is seen as collection of object files prepared by the compiler proper).

In order to support this principle of independent translation, each entity with external linkage has to be defined in one translation unit, and in only one translation unit. The user is responsible for distributing such entities between different translation units. It is considered a part of user intent, i.e. the user is supposed to decide which translation unit (and object file) will contain each definition.

The same applies to static members of the class. Static members of the class are entities with external linkage. The compiler expects you to define that entity in some translation unit. The whole purpose of this feature is to give you the opportunity to choose that translation unit. The compiler cannot choose it for you. It is, again, a part of your intent, something you have to tell the compiler.

This is no longer as critical as it used to be a while ago, since the language is now designed to deal with (and eliminate) large amount of identical definitions (templates, inline functions, etc.), but the One Definition Rule is still rooted in the principle of independent translation.

In addition to the above, in C++ language the point at which you define your variable will determine the order of its initialization with regard to other variables defined in the same translation unit. This is also a part of user intent, i.e. something the compiler cannot decide without your help.


Starting from C++17 you can declare your static members as inline. This eliminates the need for a separate definition. By declaring them in that fashion you effectively tell compiler that you don't care where this member is physically defined and, consequently, don't care about its initialization order.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
  • I just have a basic question @AnT , why *should* or *should not* static variables be defined in the header containing the class definition containing the static variable? – shauryachats Mar 24 '15 at 02:52
  • @volerag: No, absolutely not. Static members have to be defined in implementation files (each member - in one and only one implementation file of your choice), not in header files. – AnT stands with Russia Mar 24 '15 at 02:52
  • Can you please give me a reason why? – shauryachats Mar 24 '15 at 02:53
  • 3
    @volerag: Defining it in the header file will produce multiple definitions if the header file gets included into several implementation files (which is the purpose of header files). This is an ODR violation, an error. In other words, it is the same as defining an ordinary variable in a header file - it will result in an ODR error. – AnT stands with Russia Mar 24 '15 at 02:54
  • Okay, but if the header file has a guard block? I'm reasoning because if the static variable is defined in the same header, we would not have to include another translation unit just for the definition of a static variable. – shauryachats Mar 24 '15 at 02:56
  • 1
    @volerag: Guard block does not protect you from ODR violations. Guard block has nothing to do with it at all. Guard block prevents you from including the header into *the same* translation unit more than once. It does not change anything with regard to including the header into *different* translation units. And ODR violations come specifically from inclusion into *different* translation units. The rule is: don't define external variables or external non-inline functions in header files. There's no way around this rule. – AnT stands with Russia Mar 24 '15 at 02:58
  • Okay, that sounds convincing. So, basically we can conclude that static variables have explicit definition so as to modify its implementation in different translation units. That is, I can easily use static variables in a way I want with different translation units without the fear of modifying the header file containing the static variable. Is it correct? – shauryachats Mar 24 '15 at 03:01
  • @volerag: I'm not sure I understand you here. Each variable has to be defined somewhere. When it comes to a variable with external linkage, you have to tell the compiler in which specific translation unit to define it. This is how you tell the compiler where to define it. By providing a definition for your variable, you tell the compiler "I want to define it *here*, in this spot". – AnT stands with Russia Mar 24 '15 at 03:20
  • @volerag: The point at which that variable is defined will determine which object file that variable ends up in. It also partially determines the order of initialization of that variable (with regard to other variables). – AnT stands with Russia Mar 24 '15 at 03:27
  • Okay, you made it pretty clear. Thanks a lot for your time @AnT. :) – shauryachats Mar 24 '15 at 03:28
  • 2
    @volerag note the part of the answer that states this is no longer a critical reason. Local static variables are allowed inside `inline` functions, and those variables will all refer to the same object no matter how many places they are called from, even from different source files. If the C++ committee decided to drop this requirement they could at any time. – Mark Ransom Mar 29 '15 at 03:20
4

In early C++ it was allowed to define the static data members inside the class which certainly violate the idea that class is only a blueprint and does not set memory aside. This has been dropped now.

Putting the definition of static member outside the class emphasize that memory is allocated only once for static data member (at compile time). Each object of that class doesn't have it own copy.

haccks
  • 104,019
  • 25
  • 176
  • 264
1

static is a storage type, when you declare the variable you are telling the compiler "this week be in the data section somewhere" and when you subsequently use it, the compiler emits code that loads a value from a TBD address.

In some contexts, the compiler can drive that a static is really a compile time constant and replace it with such, for example

static const int meaning = 42;

Inside a function that never takes the address of the value.

When dealing with class members, however, the compiler can't guess where this value should be created. It might be in a library you will link against, or a dll, or you might be providing a library where the value must be provided by the library consumer.

Usually, when someone asks this, though, it is because they are misusing static members.

If all you want us a constant value, e.g

static int MaxEntries;
...
int Foo::MaxEntries = 10;

You would be better off with one or other of the following

static const int MaxEntries = 10;
 // or
enum { MaxEntries = 10 };

The static requires no separate definition until something tries to take the address of or form a reference to the variable, the enum version never does.

kfsone
  • 23,617
  • 2
  • 42
  • 74
0

Inside the class you are only declaring the variable, ie: you tell the compiler that there is something with this name. However, a static variable must get some memory space to live in, and this must be inside one translation unit. The compiler reserves this space only when you DEFINE the variable.

jmolgo
  • 1
  • 1
0

Structure is not variable, but its instance is. Hence we can include same structure declaration in multiple modules but we cannot have same instance name defined globally in multiple modules.

Static variable of structure is essentially a global variable. If we define it in structure declaration itself, we won't be able to use the structure declaration in multiple modules. Because that would result in having same global instance name (of static variable) defined in multiple modules causing linker error "Multiple definitions of same symbol"

Atul
  • 3,778
  • 5
  • 47
  • 87