Implicitly constructed variables in c++ - c++

I'm getting to grips with c++ and there's one language feature I'm having particular trouble getting my head around.
I'm used to declaring and initialising a variable explicitly, but in c++ we sometimes seem to declare and implicitly construct a variable.
For example in this snippet rdev seems to be implicitly constructed (as it is subsequently used to construct a default_random_engine);
random_device rdev;
default_random_engine gen(rdev());
Can someone explain what's going on here? How can I tell this apart from a simple declaration such as int myInt; ?

Can someone explain what's going on here?
These are definitions, not just declarations. A variable definition creates the variable. In the first case, there's no initialiser, indicating that it should be default-initialised.
How can I tell this apart from a simple declaration such as int myInt; ?
That's also a definition, creating the int variable and leaving it uninitialised.
You can declare a global variable without defining it:
extern int myInt;
extern indicates that it has external linkage, and is defined somewhere else. Other kinds of variable can't be declared without defining them.

random_device rdev; // creates an instance of random_device on the stack
// with default constructor (taking no arguments)
default_random_engine gen( // creates an instance of default_random_engine
// on the stack
rdev() // passing it the result of
// invocation of operator '()'
// on the instance rdev of random_device
);
Same in a more verbose form (with some C++11):
auto rdev = random_device {};
auto gen = default_random_engine { rdev.operator()() };

Can someone explain what's going on here? How can I tell this apart
from a simple declaration such as int myInt;
They are both simple definitions.
The only difference is the properties of the type. random_device needs to be constructed, so it is. int does but people cried too much, so it isn't. Frankly, int's behaviour is more of a language defect than something you actually want.
Ultimately, this is a property of the types and not the definitions.

As stated in C++ standard (8.5.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 ]
This is exactly your case: a variable definition without explicit initializer.
So, let's see what default-initialized means (8.5.7):
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.
This clearly states the difference between your two examples:
random_device is a class type, so its default constructor (the one without arguments) is implicitly called.
int is neither a class type nor an array type, so no initialization is performed, and it will have an indeterminate value until you explicitly initialize it (by assigning a value to it).

Related

C++: Are local automatic variables initialized or not? Stroustrup example

The following example is from Stroustrup C++ 4th Ed. Page 519. It was my understanding from K&R C and earlier in the Stroustrup book that local automatic variables of primitive types are undefined or not known to be initialized. Static variables of primitive types or automatic variables of a class with a default constructor are initialized.
That would mean int b should be undefined and not known to be initialized. Yet, Stroustrup adds the following code comment saying b = 0. Is this Errata? Or perhaps some behavior of calling with the default constructor?
Thank you
struct S {
string a;
int b;
};
void f(void) {
S s0 {}; // default construction: {"",0}
// ...
}
It's easy. You can leave the built-in type variables uninitialized or you can ask the compiler to zero-initialize them.
S s1; // string is default initialized, int is left uninitialized
S s2{}; // All fields are initialized.
Notice the {}. That (in this case) asks the compiler to initialize all fields.
In this line:
S s0 {};
the syntax that is used is value-initialization, in particular
when a named variable (automatic, static, or thread-local) is declared with the initializer consisting of a pair of braces.
In this case, the effect of value-initialization is that the object s0 is zero-initialized.
In this particular case, the effect is:
If T is an non-union class type, all base classes and non-static data members are zero-initialized, and all padding is initialized to zero bits. The constructors, if any, are ignored.
which implies that the int member b is zero-initialized to the value 0.
Are local automatic variables initialized or not?
It depends on the initialisation syntax that is used, the type of the variable, as well as the storage class.
That would mean int b should be undefined
No, because the example uses value initialisation, and the class in question is an aggregate.

What is instantiated when a POD structure is declared without using a default constructor?

I came upon this interesting answer when our team was dealing with a valgrind warning about unitialized members of a POD in our C++ code:
https://stackoverflow.com/a/5914697/629530
Restating the salient points, consider the following POD structure in C++:
struct C
{
int x;
int y;
};
The following invocations of constructing an object of type C invokes the default constructor and the members are initialized with that default constructor (again, copying the code and comments from Martin York's answer):
C c = C(); // Zero initialize using default constructor
C c{}; // Latest versions accept this syntax.
C* c = new C(); // Zero initialize a dynamically allocated object.
Makes sense. Martin York goes on to point out that the with the following declarations, however, the members of c are not initialized via a constructor and therefore contain undefined data:
C c; // members are random
C* c = new C; // members are random (more officially undefined).
That's interesting. I had used braced-init-list initialization of POD types before, but I didn't realize that C c; would not call the default constructor for a POD type. His answer satisfies the question, but I'd like to know specifically what is instantiated when the latter, non-default constructed c objects are declared. Specifically, the following would be helpful to me:
What is the official name for this non-default initialization of POD types? I'm having trouble googling for this mechanism because I don't know its name.
If the POD type has something less trivial than an int-type, such as a std::string, is the memory for that member also initialized with undefined values? Or is the default constructor for a std::string called for that member?
Update.
Thanks for the input. This has been duplicated to a question with this single answer:
https://stackoverflow.com/a/8860787/629530
According to that answer (and the answers to the question it is duplicated to), a declaration of the form without a parentheses is called "default initialized":
Info *p = new Info; <------- Default Initialization
For default initialization, these points about initialization are made:
To default-initialize an object of type T means:
if T is a non-POD 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, the object is zero-initialized.
I might be misunderstanding something, but the struct named C proposed above is a POD type that is not an array. Thus it should be zero initialized? The members are not, however, zero initialized but contain undefined values. How do I reconcile this?
default-initialize an object of type T means:
... otherwise, the object is zero-initialized.
No.
Your first linked answer is correct about C++11 onwards, and this is called default-initialization. It's different to default-construction or value initialization.
The second linked answer was probably correct for C++03, but is wrong for C++11 onwards (even though it was written in 2012). I don't have a copy of the '03 standard to verify, and it was a long time ago.
The effects of default initialization are:
if T is a non-POD (until C++11) class type, the constructors are considered and subjected to overload resolution against the empty argument list. The constructor selected (which is one of the default constructors) is called to provide the initial value for the new object;
if T is an array type, every element of the array is default-initialized;
otherwise, nothing is done: the objects with automatic storage duration (and their subobjects) are initialized to indeterminate values.
Local copy of N4659 agrees with the summary above:
11.6 Initializers [dcl.init]
...
(7.3) Otherwise, no initialization is performed
The section on new-expressions even refers to 11.6 and then says
Note: If no initialization is performed, the object has an indeterminate value.— end note
Current draft has
9.3 Initializers [dcl.init]
...
(7.3) Otherwise, no initialization is performed.

Relationship between initializtion and definition

Could you explain how does object definition bounds with the variable initialization, denoting initialization.
#include <iostream>
int a = 5; //definition
int main{ std::cout << a; }
sec. 1.8/1:
An object is created by a definition,[...]
a is statically initialized to 5. Initialization occurs as a part of an object definition, or it is independent from definition?
From §7/8:
A definition causes the appropriate amount of storage to be reserved and any appropriate initialization (8.5) to be done.
So yes, a definition causes initialization.
However, initialization (and object creation in general) can be caused without a definition, which is described by the omitted part of your quote (§1.8/1):
An object is created by a definition (3.1), by a new-expression (5.3.4) or
by the implementation (12.2) when needed.
An object's life time begins after its initialization has completed. It is not possible to define an object without initializing it. Even if you say int a;, you define and initialize a, although this particular kind of initialization (called "default-initialization") does nothing and leaves the object a uninitialized.

Understanding implicitly declared default costructor

I'm trying to understand how the compiler's default constructor works. I made this example:
#include <iostream>
class Base {
public:
int number;
};
class Test1 : public Base {
};
class Test2 {
public:
Base base;
};
int main() {
Test1 test1;
Test2 test2;
std::cout<<test1.number<<std::endl;
std::cout<<test2.base.number<<std::endl;
}
The output of this test program is, for test1 0, and for test2 is a uninitialized (random) number. Now my question is: why in the first case (test1) the compiler's default constructor initialize number to 0 but for test2 it doesn't?
Edit: According to answers both makes undefined behavior. So, in this program, what the compiler's default constructor does?
The value of an uninitialized object is indeterminate as per 8.5/12:
If no initializer is specified for an object, the object is default-initialized. When storage for an object with automatic or dynamic storage duration is obtained, the object has an indeterminate value, and if no initialization is performed for the object, that object retains an indeterminate value until that value is replaced (5.17).
Unfortunately for you, int falls into the category of "non-default-initialized types" as per §8.5/7:
To default-initialize an object of type T means:
if T is a (possibly cv-qualified) class type (Clause 9), the default constructor (12.1) for T is called (and the initialization is ill-formed if T has no default constructor or overload resolution (13.3) results in an ambiguity or in a function that is deleted or inaccessible from the context of the initialization);
if T is an array type, each element is default-initialized;
otherwise, no initialization is performed.
Actually in both cases number is non-default-initialized, meaning its value could be anything. It just so happened that test1 output 0 instead of some random number.
Personally, I can never remember what the implicitly defined default constructor does except in the simplest cases. So I only rely on it for the simplest cases.
I took a look at the C++11 January working paper (i.e., an edited version of the Standard published after the Standard was approved). Section 12.1 paragraph 6 (p. 243) states, "The implicitly-defined default constructor performs the set of initializations of the class that would be performed by a user-written default constructor for that class with no ctor-initializer and an empty compound-statement."
If I understand "ctor-initializer" and "compound-statement" correctly, your implicitly defined constructors are:
Test1::Test1() {}
Test2::Test2() {}
Base::Base() {}
So, in both Test1 and Test2, Base::number is never initialized (Base is, in Test2, but Base's implicit constructor doesn't initialize number).
At least, the Standard doesn't require that Base::number be initialized. Compilers are free to define things that the Standard doesn't define. The fact that you see a 0 doesn't mean the operation is defined according to the Standard, it simply means your compiler zeroed things out in this particular case.

Are file scoped static objects zero initialized before static initialization occurs for the owning translation unit?

In file maybe_use_foo.cpp:
namespace {
class Foo { /* ... */ };
Foo* const the_foo = new Foo;
}
void funtion_callable_from_another_tu_during_process_wide_initialization() {
// If we haven't yet run static initialization for this TU,
// but some other static initializer called us, ignore the request.
if (!the_foo)
return;
// OK, static initializers for this TU have run, foo exists, use it.
the_foo->doSomething();
}
So, independently of whether or not the above is advisable, does it always work? It seem to me that it assumes that statics are zero-initialized before the static initialization for the TU runs. Does the C++ standard (C++03? C++11?) guarantee that?
Another way to ask the question would be to ask what sequence of values, when interpreted as a Foo*, are held in the storage for 'the_foo'. Is it definitely {NULL/nullptr, new Foo}, or is it {undefined, new Foo}, or even something else?
Please don't suggest other ways of organizing: I'm not looking for suggestions on how to do this better, I'm looking for a deeper understanding of the legality of the technique.
C++11
[basic.start.init]/2
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.
[...]
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.
That is, yes, the variables are zero-initialized, but no, they're not zero-initialized before static initialization (but as part of static initialization).
The function in the OP will only be called during during dynamic initialization, as it is not called during zero-initialization and had to be a constexpr function to be part of constant initialization.
Yes, the C++03 standard explains in [basic.start.init]:
Objects with static storage duration (3.7.1) shall be zero-initialized (8.5) before any other initialization takes place.
8.5.1 explains:
To zero-initialize an object of type T means:
— if T is a scalar type (3.9), the object is set to the value of 0 (zero) converted to T;
[..]
Your code can cause errors. Linkers usually don't try to deeply understand initialization portions in seperate modules. Try better to provide the variable via static function, for example
namespace {
Foo* the_foo() {
static Foo* g_ = new Foo;
return g_;
}
}