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.
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.
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.
So to summarize initialization in C++ , constructor can
initialize primitive types to garbage values in memory
call default constructors on members automatically
initialize member objects with nontrivial constructors in init list
but it cannot init array properly. Ref:
C++: constructor initializer for arrays
My question is: how can I do meaningful initialization in the function body? Before entering the braces, everything has already been initialized in one way or another. The braces only contain cleaning up work, things like cout<<"This object is constructed!"
. Ref:
Use of constructor in C++
What if I want to preprocess parameter before passing it to the constructor of member object? For example:
class Foo{
public:
int x;
Foo(int y){
x = y;
}
};
class Bar{
public:
Foo foo1;
Bar(int y){
int z = superComplicatedOperation(y);
// and all other heavylifting work
foo1 = A(z);
}
};
The code above does not compile because compiler tries to init foo1 before entering the braces in constructor.
I have seen suggestions on solving this problem by providing a default constructor to Foo. So the constructor of Bar will first init foo1 to garbage value, and then assign foo1 to something meaningful in the ctor body. This is also the solution to array initialization in the quoted thread. But isn't "initializing to garbage value" an oxymoron? If the compiler wants me to do that, then it wouldn't complain about having no default ctor.
In a word, ctor is supposed to init the object in a user defined way, but I don't see any way to do a nontrivial init. Am I missing something here?
================================================================================
Clarifications: I am askingI am well aware of the Bar(int y): foo(superComplicatedOperation(y)) syntax. My question is on how to do it nicely. From a design point of view, I believe that codes in superComplicatedOperation() really should belong to the ctors. For example, say Bar takes 2 parameters (int x,int y) to initialize. We can imagine they are xy coordinates on plane. Foo also takes coordinates, but with a different reference frame. Then I need
Bar(int x,int y):foo(f1(a,b),f2(a,b))
And this kind of things quickly get ugly if ctor has a handful of params. Besides, init list looks crowded.
And if ctor body "touches" member objects, it means init list does not set members to a desired state, but rather some default zero-like states(e.g. empty vector). Therefore when calling ctor, first memory for the Bar is allocated, then members objects(subchunks of memory) go through the phases:
garbage value/uninitialized
--- init list or default member ctor --->
default "zero-like" state
--- ctor body -------------------------->
actually desired initial state
So initialization is supposed to be a two step process?
Preprocessing a parameter is fairly trivial:
class Bar
{
Foo foo;
Bar(int y) : foo(superComplicatedOperation(y)) {}
}
or you can use a C++11 delegating constructor:
class Bar
{
Foo foo;
Bar (SuperComplicatedData z) : foo(z) {}
Bar (int y) : Bar(superComplicatedOperation(y)) {}
}
What can you do in a constructor function body? Lots of things: fill containers, configure member objects, set up member object relationships, etc.
[...] constructor can
initialize primitive types to garbage values in memory
call default constructors on members automatically
This is default-initialization, which applies to every member that's not specified in the initializer list and do not have an initializer in the class definition.
initialize member objects with nontrivial constructors in init list
The member initializer list can also initialize primitive members.
but it cannot init array properly. Ref:
C++: constructor initializer for arrays
One of the answers there noted that this can now be done in C++11.
My question is: how can I do meaningful initialization in the function
body? Before entering the braces, everything has already been
initialized in one way or another. The braces only contain cleaning up
work, things like cout<<"This object is constructed!" . Ref:
Use of constructor in C++
Um...no. Frequently there's substantial logic in the constructor body proper. It's definitely not only for "cleaning up". It is true that at the time you enter the constructor body every member is initialized in some way (which may include "not initialized at all" for primitive types), but nothing says you can't assign to them or otherwise modify them. Sometimes you have to if there's some sort of circular dependencies. Sometimes the code to compute the stored value is long enough that it's far more readable inside the constructor body.
The code above does not compile because compiler tries to init foo1
before entering the braces in constructor.
I have seen suggestions on solving this problem by providing a default
constructor to Foo.
Well, you can do : foo1(A(superComplicatedOperation(y)) in your example.
So the constructor of Bar will first init foo1 to
garbage value, and then assign foo1 to something meaningful in the
ctor body. This is also the solution to array initialization in the
quoted thread. But isn't "initializing to garbage value" an oxymoron?
If the compiler wants me to do that, then it wouldn't complain about
having no default ctor.
A default ctor means that a object constructed with it is a valid object. A default ctor doesn't necessarily leave members uninitialized (or "initialized to garbage values"). Consider the default ctor for a std::vector, it had better set its internal state to something that represents an empty vector!
More fundamentally, the job of constructors (default or not) is to establish the object's invariants upon which the functions that operate on the object depend. Some objects may have no invariants, but many do (for instance, vector's internal pointer had better be either a valid pointer or null). If you have no default constructor, the compiler has no way of creating a valid object when no argument is supplied; it can't just give you something "initialized to garbage value", because it has no way of knowing whether that can in fact be a valid object of that type.
You can use an initializer list, as you should for any member variables you need to initialize.
You may prefer to initialize things to sane values and then have a function that can set the values later. It's not as clean, but if you plan to construct many objects and you can precompute the value for many of them at once it may save you some time rather than calculating the values for each object.
#include <iostream>
int superComplicatedOperation(int a)
{
return a * 10;
}
class Foo
{
public:
int x;
Foo(int y)
: x(y)
{
}
};
class Bar
{
public:
Foo foo1;
Bar(int y)
: foo1(superComplicatedOperation(y))
{
}
};
int main()
{
Bar b(7);
std::cout << b.foo1.x << "\n";
return 0;
}
class Bar {
public:
Foo foo1;
Bar(int y) : foo1(superComplicatedOperation(y)) { }
};
You can use the Constructor's initialization list for this work. It passes the values to the Ctors of the members for the first creation, this prevents the creation of a garbage object.
I guess I don't understand. I wrote code in the 1990s which has a constructor with hundreds of lines of code which does all kinds of things: opens files, instantiates dozens of objects which create linked lists and arrays based on processing file data. It certainly can initialize an array properly.
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.
Lets say I have this class:
class X {
public:
int x;
};
I saw that if I create an instance of X locally, x will not be initialize to 0, only if I create it globally.
Does this mean that the default constructor isn't synthesized by the compiler(I doubt it) for objects created localy or it will be synthesized but not zero out x value, if this is the case why is that ?
Constructors in C++ don't generally initialize members to 0. You have to explicitly initialize members with a value.
The reason that in the global case the memory is zero, is because static memory gets initialized to zero before anything else happens to it. In your case, the implicitly generated default constructor gets called afterwards, which does not touch the memory for member X.
See also this answer from Derek: Is global memory initialized in C++?
Note, however, that default constructors for structured, non-POD members (classes and structs) do automatically get called by the default constructor. It's just the POD members that are left alone by default.
X gets a synthesised constructor, but synthesised constructors do not zero-initialise primitives.
You are combining the concept of object construction with member initialization. As a general rule, don't expect C++ to initialize primitive data members for you, you'll need to do that yourself (preferably via an initialization list after the constructor.)
This is primarily for speed, as this allows allocation without initialization, which is useful if, for instance, you will be computing the values of the data members later and overwriting any "default" values.
I've found this site a useful reference in the past: http://www.cplusplus.com/doc/tutorial/variables/
Default constructors are not aware that it should initialize your member variables. If you need to initialize x to something, you better add your own constructor to do this for you:
class X {
public:
X() : x(0) { };
int x;
};