It is funny how many issues people blame on C++ that are usually inherited from C semantics compatibility, or existing C extensions at the time C++ started to get adopted.
It is funny how many issues people blame on C++ that are usually inherited from C semantics compatibility, or existing C extensions at the time C++ started to get adopted.
Let's try to write the equivalent of this error in C:
int myfunc() {
return 5;
}
static int x;
static int y = 4;
static int z = myfunc();
int main()
{};
Compiling that in gcc gives me: main.c:8:16: error: initializer element is not constant
static int z = myfunc();
^~~~~~
And it makes sense, C just wants to do a memcpy() to initialize the static variables. In C++, the only way the class is initialized is if the ctor is run. And that means running the ctor before main().Edited to add:
You're correct that 5.1.2 does not specify memcpy() as a form of initialization. But see my reply below about C11 and static storage classes.
Also add common C extensions into the soup like constructor function attributes.
Finally ISO/IEC 9899:2011, section 5.1.2.
"All objects with static storage duration shall be initialized (set to their initial values) before program startup. The manner and timing of such initialization are otherwise unspecified. Program termination returns control to the execution environment."
Don't mix what your compiler does, with what the standard requires.
Doing so only leads to unportable programs and misunderstandings.
Read section 6.7.9, constraint 4:
All the expressions in an initializer for an object that
has static or thread storage duration shall be constant
expressions or string literals.
It's syntax, not initialization.And that makes sense. However the memory is initialized before runtime could be via memcpy() it could be loaded as part of the executable and then mapped dynamically at runtime. That's what 5.1.2 is saying.
What 6.7.9 constraint 4 is saying, is that static variables can only be constant expressions.
C++ has to run code before main if a ctor is in a class that's static. There's no other way to initialize that static object.
C prevents this by requiring static storage to be initialized with constants.
namespace {
int myfunc() {
return 5;
}
int x;
int y = 4;
int z = myfunc();
};
int main()
{}
In my opinion, his point is still valid.That's why it gives you a compiler warning, and why your IDE marks it in yellow.
The same issue occurs in any language with static constructors, including Java.
#include <stdio.h>
static volatile int* x; static int y = 42;
void __attribute__((constructor)) foo() { printf("[foo] x = %p\n", x); }
int main() { x = &y; printf("[main] x = %p\n", x); return 0; }
And before you complain about that being a compiler extension yes, it is, but it's also not rare, either, and you're probably using C libraries that do this.
e.g. All Linux kernel modules use this for initialising static structs for interfacing with the kernel.
[1]: https://www.geeksforgeeks.org/__attribute__constructor-__att...
For example, the dreaded singleton using a static variable inside a function:
Singleton& get_singleton() {
static Singleton instance;
return instance;
}
Having a couple of those referenced in static initializers is a recipe for disaster. It’s a bad practice, but people unfortunately do it all the time. Those that do this are equally unequipped to realize why their program suddenly started crashing after an innocuous change.