So I am trying real hard to understand the rules of initialization in C++.
I wrote the following code:
struct B {
int i;
// this prevents the definition of an implicit default constructor
B( int j ) : i(j) {}
};
struct C {
int i;
// i is not mentioned in the initializer list
// the compiler will call default constructor for i
C() {}
};
int main() {
int x( 1 );
cout << " x = " << x << endl;
// error: no matching function for call to ‘B::B()’
//B b4 = B();
//cout << " b4.i = " << b4.i << endl;
C c1;
cout << " c1.i = " << c1.i << endl;
}
1) x is correctly initialized to 1, but I don't understand the notation "int x(1)". It's not value-initialized (we would write "int x = int()", and then x would be 0). It's not a constructor call either, because built-in types do not have constructors. Besides, the following page clearly says that: "Only objects of classes with constructors can be initialized with the function-style syntax".
http://msdn.microsoft.com/en-us/library/w7wd1177(v=vs.100).aspx
2) It won't compile if I uncomment the creation of b4. Because I defined a constructor, the compiler doesn't generate an implicit default constructor. This is fine. But why does this prevent the creation of a temporary value-initialized object using "B()"? Writing "B()" is never a constructor call, is it?
3) As explained in the comments of class C, i is not mentioned in the initializer list. Therefore, it should be default-initialized, which means undefined for int type. But the output is "c1.i = 0" every time I run the program.
Thanks.
int x(1); is the same as writing int x = 1; for built-in types.
For a type that has a user defined constructor (non-aggregate), writing T() always calls the default constructor; that's why the code doesn't compile.
c1.i is indeed uninitialized, and reading it is undefined behavior. Your compiler may be zeroing memory, especially if you don't have optimizations turned on; or it's just chance that it happens to print out zeros. You certainly cannot count on this behavior. Here's the output from clang printing garbage.
The notation int x(1); is called direct-initialization. It's defined separately for native types and for classes. In the latter case a constructor would be called.
In this case, there is no such thing as value-initialization if there's no default constructor. The rules for constructing a temporary are the same as those for constructing a named object.
Reading an uninitialized value produces undefined behavior. Running the same program again might always produce same results, but trying other programs, other machines, other platforms, may (or may not) make something else happen. Undefined literally means undefined by the standard, not crashing or random or producing an error message.
For people who rely only on the guarantees of the best-available specs, which includes all the smart folks, a program with undefined behavior is incorrect and it can be assumed to crash when you least expect.
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