Here's a minimal example:
#include <iostream>
struct B {
B() { x = 42; }
static int x;
};
int B::x;
template <int N>
struct A {
int foo() { return b.x; }
static B b;
};
template<int N>
B A<N>::b;
//template struct A<2>; // explicit instantiation with N = 2 (!)
int main(int argc, char **argv) {
std::cout << A<1>().foo() << std::endl;
return 0;
}
This program writes 42 using g++ 4.9.2, but writes 0 using Visual Studio 2015 RC. Also, if I uncomment the explicit instantiation, VS2015RC also gives 42, which is quite interesting, as the template parameter here is different from the one used in the main function.
Is this a bug? I assume that g++ is correct, as there is a reference to b inside foo, so B's constructor should be called.
EDIT: There is a simple workaround - if there is a non-static variable in B, that is referenced in A, VS2015RC will compile correctly:
// ...
struct B {
B() { x = 42; }
static int x;
int y; // <- non-static variable
};
// ...
template <int N>
struct A {
int foo() { b.y; return b.x; } // <- reference to b.y
static B b;
};
This seems to work, even though b.y, as a statement, is obviously NOP.
From [basic.start.init]:
Variables with static storage duration (3.7.1) or thread storage duration (3.7.2) shall be zero-initialized (8.5)
before any other initialization takes place. A constant initializer for an object o is an expression that is a
constant expression, except that it may also invoke constexpr constructors for o and its subobjects even
if those objects are of non-literal class types. [ ... ]
Together, zero-initialization and constant initialization are called static initialization; all other initialization is
dynamic initialization. Static initialization shall be performed before any dynamic initialization takes place.
In our case, b is statically initialized but b.x is dynamically initialized (the constructor isn't constexpr). But we also have:
It is implementation-defined whether the dynamic initialization of a non-local variable with static storage
duration is done before the first statement of main. If the initialization is deferred to some point in time
after the first statement of main, it shall occur before the first odr-use (3.2) of any function or variable
defined in the same translation unit as the variable to be initialized.
Odr-used means, from [basic.def.odr]:
A variable x whose name appears as a potentially-evaluated expression ex is odr-used by ex unless applying
the lvalue-to-rvalue conversion (4.1) to x yields a constant expression (5.20) that does not invoke any nontrivial
functions and, if [ ... ]
But evaluating b.x does not yield a constant expression, so we can stop there - b.x is odr-used by A<N>::foo(), which is also the first odr-use. So while the initialization does not have to occur before main(), it does have to occur before foo(). So if you get 0, that's a compiler error.
I would be inclined to write the code like this:
struct B {
B() {}
static int x;
};
int B::x = 42;
After all, the static (x) is defined (and therefore should be initialized) on the last line. Putting the initialization inside the constructor of B means that the static x (there is only one of them!) would be re-initialized each and every single time you construct a B. There is one static, you should initialize only once.
Related
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
Cppreference on std::ios_base::Init reads:
The header <iostream> behaves as if it defines (directly or indirectly) an instance of std::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 and W with static storage duration are ordered as follows:
3.1. If V and W have ordered initialization and the definition of V is appearance-ordered before the definition of W, or if V has partially-ordered initialization, W does not have unordered initialization, and for every definition E of W there exists a definition D of V such that D is appearance-ordered before E, then ...
3.2. Otherwise, if the program starts a thread other than the main thread before either V or W is initialized, it is unspecified in which threads the initializations of V and W occur; the initializations are unsequenced if they occur in the same thread.
3.3. Otherwise, the initializations of V and W 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;
};
Is this safe to assume that A is initialized to 1 when initializing B and C here?
struct Test {
static const int A = 1;
static const int B = A + 1;
static const int C = B + 1;
};
int main() {
printf("%i %i %i\n", Test::A, Test::B, Test::C); ==> 1 2 3
}
what about for non-integral static members
struct Test2 {
constexpr static const Test A = Test();
constexpr static const Test B = A;
constexpr static const Test C = B;
};
clang -Wall issues no warnings.
They will be initialized in the order of definition in given translation unit and before any other objects or variables.
Maybe. In this case, the initialization of A is static, so
A can be used as an integral constant expression. Which then
propagates to B. When you declare the members, they will be
initialized statically, to what the compiler has evaluated (i.e.
0 and 1), before the program even starts.
If they aren't initialized statically (which is only legal in
C++11), for any reason whatever, then they will be initialized
in the order the definitions appear in the source file, if they
are defined in the same source file. If they are not defined in
the same source file, then the order they are initialized is
unspecified.
Concerning your second example: if they are really constexpr,
there are still only constant expressions involved, so
everything will be decided at compile time, and the members will
be statically initialized.
Yes. Objects with static storage duration are always zero-initialized prior to anything else:
Variables with static storage duration (3.7.1) or thread storage duration (3.7.2) shall be zero-initialized (8.5) before any other initialization takes place.
[3.6.2§2]
Therefore any constant or dynamic initialization may assume that all other objects with static storage duration are at least zero-initialized.
Note that this does not give any guarantees for anything other than zero-initialization!
Is the following C++14/C++1y program ill-formed according to the current draft?
#include <cstddef>
template<typename T, size_t n>
struct literal_array
{
T data[n];
};
template<typename T, size_t n, size_t m>
constexpr literal_array<T, n+m> operator+(literal_array<T, n> a,
literal_array<T, m> b)
{
literal_array<T, n+m> x;
for (size_t i = 0; i < n; i++)
x.data[i] = a.data[i];
for (size_t i = 0; i < m; i++)
x.data[n+i] = b.data[i];
return x;
}
int main()
{
constexpr literal_array<int, 3> a = { 1, 2, 3 };
constexpr literal_array<int, 2> b = { 4, 5 };
constexpr auto c = a + b;
}
Clang trunk (at time of writing) gives:
error: constexpr variable 'c' must be initialized by a constant expression
constexpr auto c = a + b;
^ ~~~~~
assignment to object outside its lifetime is not allowed in a constant expression
x.data[i] = a.data[i];
^
in call to 'operator+({{1, 2, 3}}, {{4, 5}})'
constexpr auto c = a + b;
^
What does it mean "assignment to object outside its lifetime"? The lifetime of x and its subobjects encloses the function, so what is it on about?
The program is ill-formed because you are not initializing x, if you change the definition to:
literal_array<T, n+m> x = {{0}};
clang no longer complains and it compiles without error. Another solution would be to create constexpr consrtuctors.
We can find this in the draft standard section 7.1.5 The constexpr specifier paragraph 3 which says:
The definition of a constexpr function shall satisfy the following
constraints:
and includes the following bullet:
its function-body shall be = delete, = default, or a
compound-statement that does not contain
which contains this bullet (emphasis mine):
a definition of a variable of non-literal type or of static or thread
storage duration or for which no initialization is performed.
and later on we have the following example:
constexpr int uninit() {
int a; // error: variable is uninitialized
return a;
}
The complaint about the lifetime of x does not seem founded in the draft standard. The correct reason as far as I can tell should be something along the lines of object is not initialized.
The relevant quote from the draft standard on object lifetime would be section 3.8 Object lifetime paragraph 1 which says:
The lifetime of an object is a runtime property of the object. An
object is said to have non-trivial initialization if it is of a class
or aggregate type and it or one of its members is initialized by a
constructor other than a trivial default constructor. [ Note:
initialization by a trivial copy/move constructor is non-trivial
initialization. — end note ] The lifetime of an object of type T begins
when:
storage with the proper alignment and size for type T is obtained, and
if the object has non-trivial initialization, its initialization is complete.
Just in case I was missing something I also checked using std::is_trivial:
std::cout << std::boolalpha << std::is_trivial<literal_array<int, 3>>::value << std::endl ;
and the result as expected in true,.
Update
I filed a bug report for this and the reply includes this statement:
[...]The problem is that we don't yet implement the implied rule that such a function can't be invoked in a constant expression.
I have a struct with a few double values:
struct A {
double a;
double b;
}
if I create a new struct, e.g. A a, are all the members (e.g. a.a) initialized to zeroes automatically in C++?
Not by default (unless it's a variable of static storage - that is, a static or global variable).
There are a few ways to initialize a struct of this kind to "zeros":
A a = { 0.0, 0.0 };
A a = { };
A a = A();
or if you have a C++11 compatible compiler:
A a{0.0, 0.0};
A a{}
or add a constructor to the struct definition:
struct A {
double a;
double b;
A() : a(0.0), b(0.0) {}
};
8.5. Initializers [dcl.init] / 11.
If no initializer is specified for an object, the object is default-initialized; if no initialization is performed, an
object with automatic or dynamic storage duration has indeterminate value. [ Note: Objects with static or
thread storage duration are zero-initialized, see 3.6.2. — end note ]
and (ordering reversed for readability):
8.5. Initializers [dcl.init] / 6.
To default-initialize an object of type T means:
— if T is a (possibly cv-qualified) class type (Clause 9), the default constructor for T is called (and the
initialization is ill-formed if T has no accessible default constructor);
— if T is an array type, each element is default-initialized;
— otherwise, no initialization is performed. [emphasis mine]
If a program calls for the default initialization of an object of a const-qualified type T, T shall be a class type
with a user-provided default constructor.
They are default initialized. For builtin types like int or double, their value depends on where the struct is declared (as a rule of thumb (but just as that): Assume they are always garbage unless initialized).
In global scope or/and with static storage, they are all zeroes (incl. when the struct is a member of a struct which is at global scope).
At function-local scope, they are full of garbage.
Example:
#include <iostream>
struct Foo {
int x;
int y;
};
Foo foo;
int main () {
Foo bar;
std::cout << foo.x << ":" << foo.y << '\n';
std::cout << bar.x << ":" << bar.y << '\n';
}
This on the first run gives me
0:0
-1077978680:12574708
On the second run, without recompilation, this gives me:
0:0
-1075556168:12574708
A POD-struct can be initialized all zeroes using e.g. memset or just ...
Foo foo = {0}; // C and C++03
Foo foo{0}; // C++11
No. In the general case, they have unspecified values.
If you don't like this behaviour, you can provide a constructor:
struct A {
double a;
double b;
A(): a(0.0), b(0.0) {}
}
When reading the slides about constexpr the introduction is about "surprisingly dynamic initialization with consts". The example is
struct S {
static const int c;
};
const int d = 10 * S::c;
const int S::c = 5;
Alas, the audio track is missing, so are the notes, so I can only guess what is meant here.
Is it corrrect that d is "surprisingly" initialized dynamically, because S::c is defined before d? That the declaration of S::c is before d is probably not enough, the compiler needs the complete definition, right?
That said, I suspect, that in the following example d would be initialized statically?
struct S {
static const int c;
};
const int S::c = 5;
const int d = 10 * S::c; // now _after_ defn of S::c
And to take the cake, in C++11, what would have to be constexpr for full static initialization? S::c, d or both?
In the first example, d is not initialized by a constant expression, because S::c is not
a non-volatile const object with a preceding initialization,
initialized with a constant expression
(see C++11 [expr.const]p2, bullet on lvalue-to-rvalue conversions), because the initialization of S::c does not precede the initialization of d. Therefore static initialization will be used for S::c (because it is initialized by a constant expression), but dynamic initialization can be used for d.
Since static initialization precedes dynamic initialization, d would be initialized to 50 by its dynamic initializer. The compiler is permitted to convert the dynamic initialization of d to static initialization, but if it does, it must produce the value that d would have had if every variable which could have used dynamic initialization had, in fact, used dynamic initialization. In this case, d is initialized to 50 either way. See C++11 [basic.start.init]p2 for more information on this.
There is no way to add constexpr to the first example to guarantee that static initialization is used for d; in order to do that, you must reorder the initializations. However, adding constexpr will produce a diagnostic for the first example, which will at least allow you to ensure that dynamic initialization is not used (you get static initialization or a compilation error).
You can update the second case to ensure that static initialization is used as follows:
struct S {
static const int c; // do not use constexpr here
};
constexpr int S::c = 5;
constexpr int d = 10 * S::c;
It is ill-formed to use constexpr on a variable declaration which is not a definition, or to use it on a variable declaration which does not contain an initializer, so const, not constexpr must be used within the definition of struct S. There is one exception to this rule, which is when defining a static constexpr data member of a literal, non-integral type, with the initializer specified within the class:
struct T { int n; };
struct U {
static constexpr T t = { 4 };
};
constexpr T U::t;
In this case, constexpr must be used in the definition of the class, in order to permit an initializer to be provided, and constexpr must be used in the definition of the static data member, in order to allow its use within constant expressions.
I believe that the rules laid out in 3.6.2 to determine when static initialization happens do not include the initialization for d, which is therefore dynamic initialization. On the other hand, S::c is indeed statically initialized (since 5 is a constant expression). Since all static initialization happens before dynamic initialization, you get the expected result.
To make d eligible for static initialization, it has to be initialized with a constant expression. This in turn forces you to write the S::c inline:
struct S { static constexpr int c = 5; };
const int d = S::c; // statically initialized
Note that the standard permits dynamic initialization to be replaced by static initialization, which is why reordering the two lines in your original example will cause the two different sorts of initialization. As TonyK points out, you can use array[d] in the static case, but not in the dynamic case, so you can check which one is happening. With the constexpr approach, you're guaranteed to have static initialization and you don't have to rely on optional compiler behaviour.
For static initialization one needs, roughly speaking, a constant-expression initializer.
To be a constant-expression, roughly speaking, a variable needs to be of a const type and have a preceding initialization with a constant-expression.
In the first example d's initializer is not a constant-expression, as S::c isn't one (it has no preceding initialization). Hence, d is not statically initialized.
In the second example d's initializer is a constant-expression, and everything is OK.
I'm simplifying matters. In full formal standardese this would be about nine times longer.
As for constexpr specifier, no object has to be declared constexpr. It is just an additional error-check. (This is about constexpr objects, not constexpr functions).
You may declare S::c constexpr in the second variant if you want some extra error protection (perhaps 5 will start changing its value tomorrow?) Adding constexpr to the first variant cannot possibly help.
You can find out whether a constant is statically or dynamically initialised by trying to declare an array:
struct S {
static const int c;
};
const int d = 10 * S::c; // (1)
const int S::c = 5; // (2)
static char array[d];
This code fails in g++ version 4.7.0, because d is dynamically initialised. And if you exchange (1) and (2), it compiles, because now d is statically initialised. But I can't find another way to fix it, using constexpr.