This question already has answers here:
How do I use arrays in C++?
(5 answers)
Closed 6 years ago.
When declaring an array of objects, are all the objects constructed at initialization, or do they have to be constructed after initialization? Here is an example of what I am trying to explain:
Lets say I have this class:
class Object{
public:
int x = 4;
};
And this array:
Object objects[8];
If I was to access any of the variables within the objects, would I have to construct the objects first, or was that done in the array? So if I did this:
cout << objects[4].x;
Would it print out 4?
In C++11 your code is perfectly valid, it performs in-class initialization, and indeed, cout << objects[4].x; will print out 4. In previous C++ versions (C++98/03), the code is invalid, and you'd need a default constructor to initialize the variable x, like
class Object{
public:
int x;
Object(int x = 4): x(x){}
}
are all the objects constructed at initialization
Yes, all of elements of array will be default initialized.
if T is an array type, every element of the array is default-initialized;
And
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;
And
Would it print out 4?
Yes. For class Object, the implicitly-declared default constructor will be invoked here. And the member x is not initialized by the member initializer list (in default constructor), the default member initializer is applied, then x will be initialized with value 4.
Related
Suppose I have a C++ class set up as follows:
class Foo{
public:
struct Pair{
int x;
int y;
Pair(){ x = 2; y = 4; }
};
private:
Pair pairArr[16];
}
Without otherwise initializing the pairArr, what is the default value of the Pair structs inside it? Does C++ call the constructor (initializing it with x=2, y=4) or are the objects not created yet, leaving me with an array of "junk" objects until I initialize the indices myself?
I know if it is an array of a primitive data type, they are default initialized (if I had an array of ints, they would all be 0). However, I don't know if this behavior holds for more complex objects like my struct here.
Classes and structs are equivalent in c++, it's only the default access specifier that differs. So check Arrays and Classes, which says:
The normal array declaration style uses the default constructor for each object in the array (if the class has a default constructor)
From a practical point of view, do this in your struct:
Pair() : x(2), y(4) { std::cout << "Called\n"; }
and you will see the message being printed 16 times.
That's a usual approach (to add print messages to constructor to destructor) when you want to know what is called (and usually their order).
Tip: Use an initializer list, rather than assigning values inside the body of the constructor.
MyClass mc2[] = { MyClass(), MyClass() }; //this calls the constructor twice
MyClass mc1[4]; // this calls the constructor 4 times. Why?
So, my question is: why does a declaration of an array of object with no initialization cause the default constructor to be called?
In C++, an array of MyClass of size 4, is four actual objects. It is somewhat like a struct containing four members of that type, although of course you access the members using different syntax and there are other technical differences.
So, defining that array results in the 4 objects being constructed for the same reason (and under approximately the same circumstances) as defining one object of that type causes that one to be constructed.
Contrast this state of affairs with another programming language: in Java an array of MyClass of size 4 is just four pointers, which are permitted to be null. So creating it doesn't create any MyClass objects.
So, my question is: why does a declaration of an array of object with
no initialization cause the default constructor to be called?
Because that's how C++ works.
A MyClass mc1[4] is almost as if you had created four different MyClass objects:
MyClass mc1_1;
MyClass mc1_2;
MyClass mc1_3;
MyClass mc1_4;
In a class with a default constructor, this quite naturally implies that the default constructor is used to initialise each object.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What do the following phrases mean in C++: zero-, default- and value-initialization?
There are multiple places where people have said that an explicit call to the class constructor results in value initialization [when no used-defined constructors exist] and that this is not done by the default constructor [which is a do-nothing constructor] but is something completely different.
What happens actually if no constructor is called OR What is value initialization in this case ?
Firstly, what happens actually if no constructor is called
A constructor for a class-type is always called when an object is constructed, be it user-defined or compiler-generated. The object is initialized, but the members can remain un-initialized. This makes the second part of the question obsolete.
Second, is there documentation that supports/mentions/explains this behaviour ?
The all-mighty standard.
This is only true for aggregates: Consider this:
struct Holder
{
Aggregate a;
NonAggr n;
Holder(int, char) : a(), n() { }
Holder(char, int) { }
};
Holder h1(1, 'a');
Holder h2('b', 2);
Suppose Aggregate is an aggregate type. Now h1.a is value-initialized, which value-initializes each member, while h2.a is default-initialized, which default-initializes each member. The same holds for the n member, but if NonAggr is a non-aggregate class type, its default constructor will always be called.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
What is the member variables list after the colon in a constructor good for?
I found this code, its a constructor for Vector3f class.
Vector3f::Vector3f()
: x(0)
, y(0)
, z(0)
{
}
what does this definition ": x(0), y(0), z(0)" mean, and how would I go around using it?
This is called a class initilizer list. There must be 3 member variables, x y z and it is setting all of them to 0.
Check out http://www.cprogramming.com/tutorial/initialization-lists-c++.html
Class initialization lists are neat, because they allow you to set initial values of class state right before the code in the constructor is executed. This is different from just assigning values in your constructor, and makes a number of things possible:
They allow you to assign values to const members
They are the only way to pass values to the constructor of the parent class
They are the only way to instantiate stack-based member objects of the class that require some kind of values passed to the constructor.
It is called Initialization list in C++.
In initializes your variables x, y and z.
In this case(assuming x, y & z are int) it is same as:
x = 0
y = 0
z = 0
As #Charles Bailey, appropriately points out, In case the types are not int but some custom user defined class then assignment & construction maynot be the exact equivalents.
Explanation:
In an Initializer list, the types are Initialized by calling appropriate default constructors on each of the variable, for an inbuilt data type like int this is same as assignment but for custom classes an constructor operation might be different from assignment operation.
For primitive types it's the same as
x = 0;
y = 0;
z = 0;
Though actually there's subtle difference between initializer list and assignment inside a body. When we initialize fields via initializer list the constructors will be called once. If we use the assignment then fields will be first initialized with default constructors and then reassigned (via assignment operator) with actual values.
This is very trivial question regarding the use of a constructor in C++. I will present in the form of an interview dialogue (it was difficult to present it in any other forms)
interviewer - what is a constructor?
me - constructor are special functions which makes sure that all objects are initialized before their use.
interviewer - what is an initializer list?
me - that is a list where all the initialization happens. A constructor's body is entered only after all the data members are initialized, or some constructor of all the member objects are called.
interviewer - that means initialization is carried out in initializer list, not inside constructor. But you said constructor initialize the object! Didn't you? Do you want to answer my first question.
me - I think constructor does assignment, it calls assignment operator on already initialized member objects.
So my question to you can be
how initializer list works?
what lies between function's starting address & starting braces [{]?
or just answer me how to convince my interviewer.
Technically speaking, your interpretation is accurate. No members may be initialised from inside the ctor body; only in the ctor-initializer. Any member access in the ctor body may only be assignment.
All members are "initialised" before the ctor body is entered.
However, speaking more broadly, since the body always follows the initializer, it's said that — as a unit — the object is initialised once the constructor has ended... including the body.
Partly this is because, again speaking broadly, you might consider initialisation to include some business logic that you must perform in your ctor body, even though this is not the same as actual initialisation of a data member.
You're overthinking it and allowing the interviewer to confuse you.
Initializing the members of an object is not the same thing as initializing the object itself. Just because the members have sane values doesn't mean the object has been constructed. Until the constructor has completed, the object itself has not been properly initialized.
The main things about an initialisation list are efficiency and code readability.
The readability part is self-explanatory, because you know exactly where to look to see where the values are initialised. The efficiency saving comes in the fact that if you assign them values within the code of the constructor instead, then they will be assigned twice: firstly when the object is created they will be assigned the values provided by that datatype's default constructor, then they will be assigned a new value within your object's constructor. The initialisation list just insures that they are initialised with the value you specified to begin with.
for example, here is an example of an initialisation list I used in a Doubly Linked List implementation:
template <typename T>
LinkedList<T>::LinkedList()
: size(0)
, pHead(NULL)
, pTail(NULL)
{
}
Whereas the less efficient version where size, pHead and pTail get assigned twice is shown below:
template <typename T>
LinkedList<T>::LinkedList()
{
size = 0;
pHead = NULL;
pTail = NULL;
}
Essentially, you are correct but the member initializer shouldn't be considered separate from the constructor. The initializer is a part of the constructor and is called before the main body of the constructor.
When you declare an automatic variable of a built-in type, it is both a definition and a declaration. It's a declaration because an identifier is bound to a type and it's a definition because the compiler allocates storage for it.
int var1; // declares/defines var of type int
int var2 = 0; // declares/defines a var of type int and initializes it to 0
An initializer sets the variable with an initial value when it is defined but it's considered defined before the initializer.
int x = 5;
int y = 5;
int main()
{
int x = x; // x is undefined here not 5 because x refers to itself
int y[y];
int size = sizeof(y)/sizeof(int); // size is 5 (y[5]) since y isn't defined until after the enclosing bracket so y referred to the global y in the declaration.
}
There are some variables that must be initialized however. Constants and references.
It is the same with constructors. The point at which the members have been defined is right before the ctor body. This is the order that members and bases are defined when the constructor is called.
virtual base classes
base class
members--in the order in which they were declared
ctor body is executed
After leaving the constructor body, everything has been initialized.
If you don't use the initializer, then you can assume that its already defined when entering the ctor body but you can't assume it has any particular value. Again, constants and references must be initialized in the member initializer.
The initializer list is part of the constructor. Each constructor has its own.