C++ main() vs local function initialization of object - c++

I was reading inside the c++ object module,there is a topic about default constructor.if we initialize a object of some class in function like
CODE
class Test
{
public:
void show(){cout<<x<<endl;}
int x;
};
void func()
{
Test t;
t.show();
}
OUTPUT
Output is 0
but in book it is given that global objects are zero initialized and default
constructor for the creation of this object doesn't run. I'm bit confused about it.
is object zero initialized in local function and to some arbitrary value in main???

If you didn't provide a default constructor, a local object may not be zero initialized and may contain garbage.
This is defined in the standard:
Section 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.
For static and globals:
Section 3.6.2/2: Variables with static storage duration (...)
shall be zero-initialized before any other initialization takes
place.
If you have a default constructor, it is called in every case (unless you specify an initializer). This is true for global objects as for locals.
Suggestion: You could experiment this with the following default constructor:
Test() {
cout << "Default ctor: old x:" << x << endl; // for curisosity
x = 0; // now x is 0 for sure
}
You'll notice that for global objects, old x is always 0, whereas for local objects, old x may be garbage.

You can initialize x as x = 0 (or any other number you want it to be) by using a defualt constructor in your class definition. From there you can manipulate the data accordingly, or just enter the value you want x to hold in the defualt constructor.
class Test
{
public:
void show(){cout<<x<<endl;}
int x;
//Defualt Constructor
test(){
x=0;
}
};

Related

default value in struct and the constructor order

I know we can have default value for struct members. For instance, I can set default value for those members:
struct Foo {
int a = 0;
int b = 1;
int c;
}
Suppose I have another constructor for member c:
struct Foo {
int a = 0;
int b = 1;
int c;
foo(int input_c): c(input_c) {}
}
In this case, when I construct a Foo, what's the order of construction? If I do
Foo(100)
My understanding is both a and b are default constructed first then c is assigned 100, is it correct?
------------- Updates ---------------------
Part of my confusion is also the order of execution. For the default values, is it already executed before the constructors?
For instance, I can change my Foo
struct Foo {
int a = 0;
int b = 1;
int c = -1;
foo(int d) {
c += d; // Does c always started with -1?
}
}
The order initialization happens in is quite rigid, it is always the order the members are declared in.
First of all, all default in-class initializers are applied (in the order that members are declared) unless overruled by the initialization list.
Then the constructors initialization list is used and any members listed there are initialized in the order they are declared. If any of those listed members also have in-class initializers, then those don't happen and the initialization list wins and is used to initialize the members.
Then the constructor body is executed. At this point all members are already initialized, either by in-class initialization or the initializer list. But the constructor body can choose to assign new values to those initialized members.
In any case, for a given member foo it will be initialized by the in class initialization (if any) or by the initialization list (if any) or it will be default initialized. Regardless of the method used to initialize it, that initialization will always happen after another member declared before it and before another member declared after it.
For example:
struct s {
int a = 1;
int b = 42;
int c = 666;
int d;
int e;
s() : e(3), b(123) {
c = 7;
}
};
The above will always initialize a first and since it has an in-class initializer, that will be used. It's value will be 1.
b is initialized second. It has an in-class initializer, but the constructors initialization list overrules that. It will be initialized to the value 123.
Then c is initialized to the value 666.
d is uninitialized / or rather; default initialized, which for a int is the same as uninitialized, but for other types like std::string means initialized to an empty string - it depends on the type whether you have a usable value or not.
Then e is initialized to the value 3. This happens last because it is declared last. The order it is listed in in the initialization list of the constructor is irrelevant.
Then the constructor body is executed and c is assigned the value 7. So it is both initialized and subsequently assigned to - this is usually inefficient.
The object construction is now complete.
Yes, the members will be initialized in the order they are declared in the class.
So when you call Foo(100), a and b will be initialized with the default values, and then c will be initialized to 100.

std::vector initialization of class member

I have read that std::vector always initializes it's objects with their default values say for an int it is 0. The same should be applicable even for classes where the default constructor is called. However the results shown by a test program are a bit different :-
#include <iostream>
#include <vector>
using namespace std;
class A
{
public:
int i;
A(){};
};
class B
{
public:
int i;
B() = default;
};
template <typename T>
void seev (const vector<T> &v)
{
for (auto &x:v)
{
cout << x.i << ' ';
}
cout << '\n';
}
int main()
{
vector<int> vi(5); // just to show that std::vector always default initializes values & hence int will be 0 here
vector<A> va(5);
vector<B> vb(5);
for (auto x: vi)
cout << x << ' ';
cout << '\n';
seev (va);
seev (vb);
return 0;
}
The output is :-
0 0 0 0 0
8854016 0 8847696 0 8854016
0 0 0 0 0
My question is why was the value of member i undefined for A & not for B ? What difference did the constructor signatures :-
A() {}
&
B() = default;
make ?
There is a difference between default initialization and value initialization. The difference is shown for B but not for A:
When a class has a non-= defaulted constructor, this constructor is called when either default or value initialization is used. Its responsibility is to initialize all members appropriately.
When a class either has no constructor or an = defaulted default constructor the initialization of the members depends on how the object is constructed: when initializing the object without parenthesis default initialization is done which leaves subobjects without a default constructor uninitialized. When initializing the object with parenthesis value initialization is done which value initializes all subobjects. Value initialization of built-in types mean they get a suitable zero value while default initialization of built-in types means they are left uninitialized.
Since A has an explicitly written default constructor, its constructor needs to initialize all members which aren't of class type with a default constructor. B has an implicitly written default constructor and default or value initialization is performed as necessary for the subobjects.
The objects in a std::vector<T> are constructed using T() (if no other arguments are provides as is the case, e.g., for push_back() or emplace_back()). For A members that means they are left uninitialized, for B members that means they are zero initialized.
When creating a vector with a specific size, the vector doesn't set default values, it uses something called value initialization which is something completely different.
For primitive types, like e.g. int, that means the value will be zero-initialized (i.e. zero). But for objects with constructors the default constructor (if it has one) will be used.
In the case of your A class, the default constructor does not initialize the i member variable, so it will be uninitialized and have an indeterminate value, by printing that value you have undefined behavior.
As for the B class it's a POD type which means that value initialization of the whole object will also value-initialize all members. B is a POD type because it has a trivial default constructor (which A does not have).
A() {};
You are not initializing A::i in A() so its value is unspecified after value initialization. This behaviour is different to what you would get with a compiler-provided default constructor.
A() = default;
Defining as default on the other hand has the effect of providing a constructor with the same semantics of the compiler-synthesized default constructor. That is to say, A::i would get value-initialized (and therefore zero-initialized) when an A object is value initialized with expressions such as A() or A{}.
Note: this can be fixed by either dropping the definition of the default constructor, define it as default, or explicitly initialize i.
struct A
{
// Compiler provided A() will initialize i
// when A is value initialized
int i;
};
or, equivalently in terms of initialization semantics,
struct A
{
int i;
A() = default; // useful if other constructors defined
};
An "empty" constructor will not initialize anything, so the fact that va contains zero is just luck/coincidence. The default constructor will do nothing either, so they will produce the same thing. What you are seeing is undefined behaviour (or unspecified behaviour perhaps - as we shouldn't really expect world war three to break out because of an uninitialized variable).
The problem is that std::vector is supposed to call the default constructor & not set the values by default. The default constructor of int sets it's value to 0 hence you get a std::vector<int> with all values initialized with 0. However you default constructor of A is empty & hence it doesn't initialize i with any value. If you define the constructor as :-
A() { i = 0; }
Then your vector would definitely initialize the i of the objects of A with 0. What default does is this :-
#include <iostream>
#include <vector>
using namespace std;
class A
{
public:
A()
{
cout << "Default constructed A\n";
}
A (A &obj)
{
cout << "Copy constructed A\n";
}
};
class X
{
int x;
double d;
bool b;
A obj;
public:
X() = default;
void show()
{
cout << fixed << x << ' ' << d << ' ' << b << '\n';
}
};
int main()
{
cout << boolalpha;
vector<X> v(1);
v[0].show();
return 0;
}
/* Output :-
Default constructed A
0 0.000000 false
*/
What B() = default; roughly means as far I get from this test code that it is a replacement for :-
B()
{
i = 0;
d = 0.00;
b = false;
// obj is default initialized
}
ie the initialization of the data members with their default values (for primitives) or default constructors (for classes). But this is only for runtime initialization which means for locally created objects the definition is same as B() = {}.
So the thing was that class A had a user defined constructor (with an empty body) & hence didn't initialize because that's how the programmer defined it. On the other hand class B had a constructor that was left on to the compiler to call implicitly. Hence for local objects it didn't do any specific initialization but for dynamic objects (like that of a std::vector) it did the value type initialization.

Does modern c++ will have default initialized value

I am new to c++ and I want to learn best practice of c++. I got one question, does the modern c++ compiler will auto assign default value for an uninitialized variable? If yes, does it mean that we do not need to assign default value to a variable or it depends on system?
Thank you for your help and clarification.
Only static and global data is always initialised...
int w; // will be 0
static int x; // will be 0
void f() { static int x; /* will be 0 the first time this scope's entered */ }
struct S
{
int n_;
};
S s_; // s_.n_ will be 0 as s_ is global
int main()
{
S s; // s.n_ will be uninitialised
// undefined behaviour to read before setting
}
For any other variables they must have - at some level in the code - explicit initialisation before they're read from. That might not be visible at the point a variable is declared though - it could be in a default constructor or an assignment. You can also cause initialisation like this:
int x{}; // will be 0
int* p = new int{}; // *p will be 0
Default initialization is performed in three situations:
1) when a variable with automatic, static, or thread-local storage duration is declared with no initializer.
2) when an object with dynamic storage duration is created by a new-expression with no initializer or when an object is created by a new-expression with the initializer consisting of an empty pair of parentheses (until C++03).
3) when a base class or a non-static data member is not mentioned in a constructor initializer list and that constructor is called.
More information here:
http://en.cppreference.com/w/cpp/language/default_initialization
With regard to what the compiler will do I think its more of the inverse, for example:
int x; // still must be inited, will contain random data
if (some_func())
{
// some devs will do this for "performance" - i.e don't assign a value to x
x = 2;
}
But if you write:
int x = 0;
if (some_func())
{
x = 2;
}
The compiler will optimize this to:
int x;
if (some_func())
{
x = 2; // Yes this code is actually the first example again :)
}
Assuming x is not used else where in the function.

Is modify const in constructor C++ standard?

Is modify const in constructor C++ standard? I was modifying my struct removing fixed-values(default member initializer) to set it later, at constructor-time but I forget to remove const keyword and noticied it later. To my surprise I didn't get a compile-error, it just worked fine but for test case 2 it give a compiler. How are they different?
test case 1:
struct A
{
const int x = 2;
A()
: x(3)
{
}
};
test case 2:
struct A
{
const int x = 2;
A()
{
x = 3; // compile error! error: read-only variable is not assignable
}
};
In the first example you are initializing the constant variable, in the second you are assigning a value to it, after the variable is default constructed. These are different operations and assignment is not possible for constants after their initialization.
This syntax was added in C++11:
struct A
{
const int x = 2;
In this case the 2 is like a "default" value to be used for initialization of x. If you initialize x in your constructor's initialization list, then that is the value used. However if you did not do so, then 2 is used.
This was added to C++11 to avoid the tedium of having to repeat things in the initialization lists if you had multiple constructors.
The thing is that the object must be fully initialized before the body of your constructor can proceed to start playing with it. This means that there must be reserved enough space in memory to which the instance of new object will be placed.
If you declare data member (int x) to be const, you prohibit yourself from ever changing it's value, once it is created, this means that the value must be set during it's creation.
In example 1 you first create the int x and set it to value 3 (which will reside in memory reserved for your object) and only after that the body of your constructor executes.
In example 2 you create new object (with some value for your int x) and than you try to modify it in your constructor, which is prohibited by the const keyword.

Does a c++ struct have a default constructor?

I wrote the following code snippet:
void foo()
{
struct _bar_
{
int a;
} bar;
cout << "Value of a is " << bar.a;
}
and compiled it with g++ 4.2.1 (Mac). The output is "Value of a is 0".
Is it true to say that data members of a struct in c++ are always initialized by default (compared to c)? Or is the observed result just coincidence?
I can imagine that structs in c++ have a default constructor (since a struct and a class is almost the same in c++), which would explain why the data member a of bar is initialized to zero.
The simple answer is yes.
It has a default constructor.
Note: struct and class are identical (apart from the default state of the accesses specifiers).
But whether it initializes the members will depends on how the actual object is declared. In your example no the member is not initialized and a has indeterminate value.
void func()
{
_bar_ a; // Members are NOT initialized.
_bar_ b = _bar_(); // Members are zero-initialized
// From C++14
_bar_ c{}; // New Brace initializer (Members are zero-initialized)
_bar_* aP = new _bar_; // Members are NOT initialized.
_bar_* bP = new _bar_(); // Members are zero-initialized
// From C++14
_bar_ cP = new _bar_{}; // New Brace initializer (Members are zero-initialized)
}
// static storage duration objects
// i.e. objects at the global scope.
_bar_ c; // Members are zero-initialized.
The exact details are explained in the standard at 8.5 Initializers [dcl.init] paragraphs 4-10. But the following is a simplistic summary for this situation.
A structure without a user defined constructor has a compiler generated constructor. But what it does depends on how it is used and it will either default initialize its members (which for POD types is usually nothing) or it may zero initialize its members (which for POD usually means set its members to zero).
PS. Don't use a _ as the first character in a type name. You will bump into problems.
Is it true to say that data members of a struct in c++ are always initialized by default (compared to c)? Or is the observed result just coincidence?
It is a coincidence.
Your code invokes Undefined Behavior; unless you explicitly set the members to 0 they can be anything.
Not an answer, but you might take it to be... if you want to try it:
void foo() {
struct test {
int value;
} x;
std::cout << x.value << std::endl;
x.value = 1000;
}
int main() {
foo();
foo();
}
In your example, the memory already had the 0 value before the variable was created, so you can call it a lucky coincidence (in fact, some OS will zero out all memory before starting a process, which means that 0 is quite a likely value to find in a small short program...), the previous code will call the function twice, and the memory from the first call will be reused in the second one, chances are that the second time around it will print 1000. Note however that the value is still undefined, and that this test might or not show the expected result (i.e. there are many things that the compiler can do and would generate a different result...)
Member variables of a struct are not initialized by default. Just like a class (because a struct is exactly the same thing as a class, only in struct the members are public by default).
Do not rely on this functionality it is non-standard
just add
foo() : a() {}
I can't remember the exact state of gcc 4.2 (i think it is too old) but if you were using C++11 you can do the following
foo()=default;