Hi Jason. I didn't find a comment on default initialization of static members (esp. integral ones). In fact you need to write int foo::i so that the linker can find it, but it will be automatically initialized with 0! This line would be sufficient: int foo::i; (This is valid for all objects stored in the static memory, the linker is in charge of initializing the static objects.)
– NicoJul 18 '12 at 9:59

1

The answers below do not apply for a template class. They say: the initialization must go into the source file. For a template class, this is neither possible, nor necessary.
– Joachim WJun 9 '16 at 15:20

17 Answers
17

The class declaration should be in the header file (Or in the source file if not shared).
File: foo.h

class foo
{
private:
static int i;
};

But the initialization should be in source file.
File: foo.cpp

int foo::i = 0;

If the initialization is in the header file then each file that includes the header file will have a definition of the static member. Thus during the link phase you will get linker errors as the code to initialize the variable will be defined in multiple source files.

Note: Matt Curtis: points out that C++ allows the simplification of the above if the static member variable is of const int type (e.g. int, bool, char). You can then declare and initialize the member variable directly inside the class declaration in the header file:

Yes. But I am assuming the question has been simplified. Technically the declaration and definition can all be in a single source file. But that then limits the use of class by other classes.
– Martin YorkOct 9 '08 at 3:40

10

actually not just POD, it has to be an int type as well (int, short, bool, char...)
– Matt CurtisOct 9 '08 at 4:56

8

Note that this isn't just a question of how the value is initialized: const integral types defined like this may be turned into compile time constants by the implementation. This isn't always what you want, since it ups the binary dependency: client code needs recompilation if the value changes.
– Steve JessopOct 9 '08 at 11:19

4

@Martin: in addition to the correction s/POD/integral type/, if the address is ever taken then there needs to be a definition also. Strange as it may sound, the declaration with initializer, in the class definition, is not a definition. The templated const idiom provides a workaround for the cases where you need the definition in a header file. Another and simpler workaround is a function that produces the value of a local static constant. Cheers & hth.,
– Cheers and hth. - AlfOct 15 '10 at 18:13

3

You might add a clarification that int foo::i =0; should not be inside a function (including the main function). I had it at the beginning of my main function and it doesn't like that.
– qwerty9967Apr 15 '13 at 19:33

This is a valid point. I will add this too my explanation. But it should be noted this only works for POD types.
– Martin YorkOct 9 '08 at 3:44

Since when, C++ allows to be just good with declaration in-class and no definition for integral types. Since C++98 itself or C++03 or when ? Please share authentic links please. C++ standard wording is not in sync with the compilers. They mention the member shall still be defined if they are used. So, I don't need the C++ Standard quoting though
– smRajSep 20 '14 at 15:42

1

I wonder why private variables can be initialized outside Class here, can this be done for non-static variables also.
– darth_coderJul 10 '15 at 11:19

Header files get compiled once for every .cpp file that directly or indirectly #includes them, and code outside of any function is run at program initialization, before main().

By putting: foo::i = VALUE; into the header, foo:i will be assigned the value VALUE (whatever that is) for every .cpp file, and these assignments will happen in an indeterminate order (determined by the linker) before main() is run.

What if we #define VALUE to be a different number in one of our .cpp files? It will compile fine and we will have no way of knowing which one wins until we run the program.

Never put executed code into a header for the same reason that you never #include a .cpp file.

include guards (which I agree you should always use) protect you from something different: the same header being indirectly #included multiple times while compiling a single .cpp file

You're right about this of course, except in the case of a class template (which isn't asked about, but I happen to be dealing with a lot). So if the class is fully defined and not a class template, then put these static members in a separate CPP file, but for class templates the definition has to be in the same translation unit (e.g., the header file).
– monkey0506Jan 18 '13 at 20:22

@monkey_05_06: That just seems to be an argument to avoid static member in templated code: You already end up with one static member for each instantiation of the class. the problem is worsened by possibly compiling the header into multiple cpp files... You could get a raft of conflicting definitions.
– Joshua ClaytonFeb 26 '13 at 5:13

Your argument is really huge stretch. First you cannot #define VALUE because macros name has ot be a valid identifier. And Even if you could - who would do that? Header files are for declaration - ? C'mon.. The only cases where you should avoid putting values in the header is to fight odr-used. And putting the value in the header may lead to unnecessary recompilation whenever you need to change the value.
– Aleksander FularMar 4 '16 at 15:39

Is the correct syntax for initializing the variable, but it must go in the source file (.cpp) rather than in the header.

Because it is a static variable the compiler needs to create only one copy of it. You have to have a line "int foo:i" some where in your code to tell the compiler where to put it otherwise you get a link error. If that is in a header you will get a copy in every file that includes the header, so get multiply defined symbol errors from the linker.

"A static data member may be declared inline. An inline static data member can be defined in the class definition and may specify a default member initializer. It does not need an out-of-class definition:"

I don't have enough rep here to add this as a comment, but IMO it's good style to write your headers with #include guards anyway, which as noted by Paranaix a few hours ago would prevent a multiple-definition error. Unless you're already using a separate CPP file, it's not necessary to use one just to initialize static non-integral members.

This only works if you have only one compile unit that includes foo.h. If two or more cpps include foo.h, which is a typical situation, each cpp would declare the same static variable so the linker would complain with multiple definition of `foo::i' unless you use a package compilation with the files (compile only one file that include all cpps). But although package compilation is great the solution to the problem is to declare (int foo::i = 0;) in a cpp!
– Alejadro XalabarderDec 31 '13 at 2:51

As the ListInitializationGuard is a static variable inside SomeClass::getList() method it will be constructed only once, which means that constructor is called once. This will initialize _list variable to value you need. Any subsequent call to getList will simply return already initialized _list object.

Of course you have to access _list object always by calling getList() method.

You can also include the assignment in the header file if you use header guards. I have used this technique for a C++ library I have created. Another way to achieve the same result is to use static methods. For example...

We would only have to use the set_default(int x) method and our static variable would be initialized.

This would not be in disagreement with the rest of the comments, actually it follows the same principle of initializing the variable in a global scope, but by using this method we make it explicit (and easy to see-understand) instead of having the definition of the variable hanging there.

This is a common problem for those who starts with C++. Static class member must be initialized in single translation unit i.e. in single source file.

Unfortunately, the static class member must be initialized outside of the class body. This complicates writing header-only code, and, therefore, I am using quite different approach. You can provide your static object through static or non-static class function for example:

Thank you for your interest in this question.
Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).