Following code
#include <iostream>
struct A {
A() {
std::cout << std::endl;
}
};
struct B {
static inline A a;
};
int main() {
}
succeeds after compiling with gcc, but crashes with segmentation fault after compiling with clang. Is the code not standard or is clang wrong?
https://godbolt.org/z/tEvfrW
A static member function can be called even if no objects of the class exist and the static functions are accessed using only the class name and the scope resolution operator ::. A static member function can only access static data member, other static member functions and any other functions from outside the class.
Static data members are class members that are declared using static keywords. A static member has certain special characteristics. These are: Only one copy of that member is created for the entire class and is shared by all the objects of that class, no matter how many objects are created.
For the static variables, we have to initialize them after defining the class. To initialize we have to use the class name then scope resolution operator (::), then the variable name. Now we can assign some value.
static. The static keyword can be used to declare variables and functions at global scope, namespace scope, and class scope. Static variables can also be declared at local scope. Static duration means that the object or variable is allocated when the program starts and is deallocated when the program ends.
The constructor is called when an object of a class is created. It can be used to set initial values for object attributes: Note that the constructor name must match the class name, and it cannot have a return type (like void ). Also note that the constructor is called when the object is created.
All classes have constructors by default: if you do not create a class constructor yourself, C# creates one for you. However, then you are not able to set initial values for fields. Constructors save time! Take a look at the last example on this page to really understand why.
Note that the constructor name must match the class name, and it cannot have a return type (like void ). Also note that the constructor is called when the object is created. All classes have constructors by default: if you do not create a class constructor yourself, Java creates one for you.
Learn about Static Member in C++. Member objects of a class are the class member variables that are objects of another class. If a class has an object of another class as a member variable that binds them in the Has-A relation. A class can have a static member, that can be declared by using the static keyword.
Cppreference on std::ios_base::Init
reads:
The header
<iostream>
behaves as if it defines (directly or indirectly) an instance ofstd::ios_base::Init
with static storage duration: this makes it safe to access the standard I/O streams in the constructors and destructors of static objects with ordered initialization (as long as#include <iostream>
is included in the translation unit before these objects were defined).
You do include <iostream>
before B::a
, but the initialization of B::a
(with B::a
being static inline
variable) is not part of ordered initialization, so it can be initialized before std::ios_base::Init
. It seems that Clang (some versions, at least) does exactly this. This is a valid behaviour.
The standard reads ([basic.start.dynamic]):
- Dynamic initialization of a non-local variable with static storage duration is unordered if the variable is an implicitly or explicitly instantiated specialization, is partially-ordered if the variable is an inline variable that is not an implicitly or explicitly instantiated specialization, and otherwise is ordered.
So, an initialization of instance of std::ios_base::Init
is ordered, and initialization of B::a
is partially-ordered.
- Dynamic initialization of non-local variables
V
andW
with static storage duration are ordered as follows:3.1. If
V
andW
have ordered initialization and the definition ofV
is appearance-ordered before the definition ofW
, or ifV
has partially-ordered initialization,W
does not have unordered initialization, and for every definitionE
ofW
there exists a definitionD
ofV
such thatD
is appearance-ordered beforeE
, then ...3.2. Otherwise, if the program starts a thread other than the main thread before either
V
orW
is initialized, it is unspecified in which threads the initializations ofV
andW
occur; the initializations are unsequenced if they occur in the same thread.3.3. Otherwise, the initializations of
V
andW
are indeterminately sequenced.
3.1 and 3.2 don't apply. So we have indeterminately sequenced initializations.
You can make B::a
a non-inline
static variable or somehow force std::ios_base::Init
initialization before using std::cout
, for example:
struct A {
A() {
std::cout << std::endl;
}
std::ios_base::Init init;
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With