Does modern c++ will have default initialized value - c++

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.

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.

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

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;
}
};

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.

Initialisation and assignment

What EXACTLY is the difference between INITIALIZATION and ASSIGNMENT ?
PS : If possible please give examples in C and C++ , specifically .
Actually , I was confused by these statements ...
C++ provides another way of initializing member variables that allows us to initialize member variables when they are created rather than afterwards. This is done through use of an initialization list.
Using an initialization list is very similar to doing implicit assignments.
Oh my. Initialization and assignment. Well, that's confusion for sure!
To initialize is to make ready for use. And when we're talking about a variable, that means giving the variable a first, useful value. And one way to do that is by using an assignment.
So it's pretty subtle: assignment is one way to do initialization.
Assignment works well for initializing e.g. an int, but it doesn't work well for initializing e.g. a std::string. Why? Because the std::string object contains at least one pointer to dynamically allocated memory, and
if the object has not yet been initialized, that pointer needs to be set to point at a properly allocated buffer (block of memory to hold the string contents), but
if the object has already been initialized, then an assignment may have to deallocate the old buffer and allocate a new one.
So the std::string object's assignment operator evidently has to behave in two different ways, depending on whether the object has already been initialized or not!
Of course it doesn't behave in two different ways. Instead, for a std::string object the initialization is taken care of by a constructor. You can say that a constructor's job is to take the area of memory that will represent the object, and change the arbitrary bits there to something suitable for the object type, something that represents a valid object state.
That initialization from raw memory should ideally be done once for each object, before any other operations on the object.
And the C++ rules effectively guarantee that. At least as long as you don't use very low level facilities. One might call that the C++ construction guarantee.
So, this means that when you do
std::string s( "one" );
then you're doing simple construction from raw memory, but when you do
std::string s;
s = "two";
then you're first constructing s (with an object state representing an empty string), and then assigning to this already initialized s.
And that, finally, allows me to answer your question. From the point of view of language independent programming the first useful value is presumably the one that's assigned, and so in this view one thinks of the assignment as initialization. Yet, at the C++ technical level initialization has already been done, by a call of std::string's default constructor, so at this level one thinks of the declaration as initialization, and the assignment as just a later change of value.
So, especially the term "initialization" depends on the context!
Simply apply some common sense to sort out what Someone Else probably means.
Cheers & hth.,
In the simplest of terms:
int a = 0; // initialization of a to 0
a = 1; // assignment of a to 1
For built in types its relatively straight forward. For user defined types it can get more complex. Have a look at this article.
For instance:
class A
{
public:
A() : val_(0) // initializer list, initializes val_
{}
A(const int v) : val_(v) // initializes val_
{}
A(const A& rhs) : val_(rhs.val_) // still initialization of val_
{}
private:
int val_;
};
// all initialization:
A a;
A a2(4);
A a3(a2);
a = a3; // assignment
Initialization is creating an instance(of type) with certain value.
int i = 0;
Assignment is to give value to an already created instance(of type).
int i;
i = 0
To Answer your edited Question:
What is the difference between Initializing And Assignment inside constructor? &
What is the advantage?
There is a difference between Initializing a member using initializer list and assigning it an value inside the constructor body.
When you initialize fields via initializer list the constructors will be called once.
If you use the assignment then the fields will be first initialized with default constructors and then reassigned (via assignment operator) with actual values.
As you see there is an additional overhead of creation & assignment in the latter, which might be considerable for user defined classes.
For an integer data type or POD class members there is no practical overhead.
An Code Example:
class Myclass
{
public:
Myclass (unsigned int param) : param_ (param)
{
}
unsigned int param () const
{
return param_;
}
private:
unsigned int param_;
};
In the above example:
Myclass (unsigned int param) : param_ (param)
This construct is called a Member Initializer List in C++.
It initializes a member param_ to a value param.
When do you HAVE TO use member Initializer list?
You will have(rather forced) to use a Member Initializer list if:
Your class has a reference member
Your class has a const member or
Your class doesn't have a default constructor
Initialisation: giving an object an initial value:
int a(0);
int b = 2;
int c = a;
int d(c);
std::vector<int> e;
Assignment: assigning a new value to an object:
a = b;
b = 5;
c = a;
d = 2;
In C the general syntax for initialization is with {}:
struct toto { unsigned a; double c[2] };
struct toto T = { 3, { 4.5, 3.1 } };
struct toto S = { .c = { [1] = 7.0 }, .a = 32 };
The one for S is called "designated initializers" and is only available from C99 onward.
Fields that are omitted are automatically initialized with the
correct 0 for the corresponding type.
this syntax applies even to basic data types like double r = { 1.0
};
There is a catchall initializer that sets all fields to 0, namely { 0 }.
if the variable is of static linkage all expressions of the
initializer must be constant expressions
This {} syntax can not be used directly for assignment, but in C99 you can use compound literals instead like
S = (struct toto){ .c = { [1] = 5.0 } };
So by first creating a temporary object on the RHS and assigning this to your object.
One thing that nobody has yet mentioned is the difference between initialisation and assignment of class fields in the constructor.
Let us consider the class:
class Thing
{
int num;
char c;
public:
Thing();
};
Thing::Thing()
: num(5)
{
c = 'a';
}
What we have here is a constructor that initialises Thing::num to the value of 5, and assigns 'a' to Thing::c. In this case the difference is minor, but as was said before if you were to substitute int and char in this example for some arbitrary classes, we would be talking about the difference between calling a parameterised constructor versus a default constructor followed by operator= function.

Variable initialising and constructors

I am currently taking a c++ course and trying to get a deep understanding of the whole thing.
I came up with some theories, it would be great if somebody could confirm them:
Every variable (local,global,staic,member and non-member) is guaranteed to have its ctor called before first use
The ctors of primitives like int are essentially no-ops, so we have explicitly assign a value, there is no default zero value.
the following classes are semantically the same (and should generate identical code)
class A
{
int n;
};
and
class A
{
int n;
public:
A() : n() {}
};
and
class A
{
int n;
public:
A() { n = int(); }
};
The variable n is in every case still uninitialized.
EDIT:
It seem that I absolutetly underestimated the complexity of this subject, most of my assumptions were wrong. Now Iam still trying to find out the basic rules of object initialisation.
I'm afraid you are wrong. When you say:
int n = int();
Then n (and all other POD types) will zero initialised.
Also, make sure that you are very clear in your mind about the difference between initialisation and assignment - this is quite important in C++:
int n = int(); // initialisation
n = 0; // assignment
You might find this interesting.
The difference between new Foo and new
Foo() is that former will be
uninitialized and the latter will be
default initialized (to zero) when Foo
is a POD type. So, when not using the
form with the parens, the member "a"
can contain garbage, but with the
parens "a" will always be initialized
to 0.
No, the variable is only left uninitialised in the first case.
For a member that is a class with a user-defined constructor, the situation is simple: a constructor is always called.
Built-in types (and 'plain old data' structs) may be left uninitialised, as in your first example. Although they don't have user-supplied constructors, using the construction syntax (your other two examples) initialises them to zero.
The reason for this slightly tricky rule is to avoid undue overhead; for example if you defined:
struct S
{
int array[1024*1024];
};
with the intention of only assigning values as you needed them, you wouldn't want the compiler to whitewash 4Mb of memory with zeroes whenever you construct one.
class A
{
int n;
};
Only memory is allocated, no initialization done for n.
class A
{
int n;
public:
A() : n() {}
};
Here n is initialized with 0.
class A
{
int n;
public:
A() { n = int(); }
};
Here n is first constructed (without any default value),
then int() causes a temp int to be created with value 0
Which is then assigned to n;