2

Let's consider a code

header:

class uid
{
public:
    uid () {++i; }
    static int i;
};

class foo
{
public:
    const static uid id;
}   

source:

static int uid::i = 0;

The header could be included into several source files, shared between compiler units and libraries.

Is it guaranteed that there would be only one instance off foo::id, that foo::id::id() would be called once at run-time and, the most important thing, would foo::id.i be the same everywhere in the program and it's libraries? On the other hand another shared header could have bar class with it's own static const uid id which is expected to differ from foo's one. Is it also guaranteed? If so, where actually foo::id symbol is stored, especially in case of shared (dynamic-linked) libraries.

On some reason c++ disables

class foo
{
public:
    const static int id = create_uid(); // forbidden
}   

allowing only compile-time const initialisation or initialization in source file. So there was some reason to disable this kind of approach.

Nick
  • 970
  • 10
  • 20

1 Answers1

4

Yes, that is guaranteed.

The symbol lives in the translation unit built from the source file where the object was defined. Indeed, that's why we have to define it in one!

The linker makes sure all the references from the copies of that header across your project all match up to the sole definition.

As for why C++ doesn't let you initialise static members inline: it does, but not in C++98. You need C++17 for that.

Asteroids With Wings
  • 17,071
  • 2
  • 21
  • 35
  • There could be actually no source file where ```foo```'s members are defined (and even no ```foo``` object at all) - everything is in header. So one may afraid that a compiler could store own copy of ```foo::id``` in each source file where the header is included. Yes, it's about c++98. – Nick May 13 '20 at 18:22
  • @Nick If there's no definition of `foo`, then there is no `foo` and your program will not be buildable (you'll get a linker error; you can test that for yourself). No need for fear. :) – Asteroids With Wings May 13 '20 at 18:23
  • 1
    @TedLyngmo [Not exclusively](https://stackoverflow.com/q/46874055/4386278) – Asteroids With Wings May 13 '20 at 18:32
  • To be equally fair, I didn't consider `inline` :-) Initializing a `const static` is ok in c++98 too afaik, but calling a function to initialize it isn't. – Ted Lyngmo May 13 '20 at 18:35
  • 1
    @TedLyngmo I was thinking of NSDMIs for C++11 anyway Ah well. – Asteroids With Wings May 13 '20 at 18:36
  • 1
    there used to be a caveat allowing integral types (int) but not float, double to be initialized inline. was that restriction also dropped with C++17? – Cee McSharpface May 13 '20 at 18:59
  • 2
    @CeeMcSharpface You can pretty much [do whatever you like](https://coliru.stacked-crooked.com/a/cbb90f78a2b55b37) now. Though I'm not sure your premise is true. _(Edit: never mind; [it is](https://coliru.stacked-crooked.com/a/03bc1ac061ba2818))_ C++11 allowed it with `constexpr`. – Asteroids With Wings May 13 '20 at 19:00