Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Two ways of calling default constructor

I have the following code:

struct B
{
 //B() {}
 int x;
 int y;
};

void print(const B &b) 
{
 std::cout<<"x:"<<b.x<<std::endl;
 std::cout<<"y:"<<b.y<<std::endl;
 std::cout<<"--------"<<std::endl;
}

int main()
{
 B b1 = B(); //init1
 B b2; //init2

 print(b1);
 print(b2);

 return 0;
}

When I start program (vs2008, debug) I have the following output:

x:0
y:0
--------
x:-858993460
y:-858993460
--------

As you can see b1.x and b1.y have 0 value. why? What's difference between init1 and init2?

When I uncomment B constructor I have the following output:

x:-858993460
y:-858993460
--------
x:-858993460
y:-858993460
--------

Can somebody explain the reason of this behaviour? Tnx in advance.

like image 779
mt_serg Avatar asked Oct 09 '09 09:10

mt_serg


People also ask

What are the different ways of calling constructor?

The constructors can be called explicitly or implicitly. The method of calling the constructor implicitly is also called the shorthand method. Example e = Example(0, 50); // Explicit call.

How many ways we can call constructor?

Constructor chaining can be done in two ways: Within same class: It can be done using this() keyword for constructors in the same class. From base class: by using super() keyword to call the constructor from the base class.

What are various types of default constructors?

Default Constructors in C++ The two main types of constructors are default constructors and parameterized constructors. Default constructors do not take any parameters. If a default constructor is not provided by the programmer explicitly, then the compiler provides a implicit default constructor.


3 Answers

Default constructor for POD types fills it with zeros. When you explicitly define your own constructor you are not initialize x and y and you'll get random values (in VS debug they are filled with exact values, but in release they will be random).

It is according to C++03 Standard 8.5/5:

<...>To value-initialize an object of type T means:
— if T is a class type (clause 9) with a user-declared constructor (12.1), then the default constructor for T is called (and the initialization is ill-formed if T has no accessible default constructor);
— if T is a non-union class type without a user-declared constructor, then every non-static data member and base-class component of T is value-initialized;
— if T is an array type, then each element is value-initialized;
— otherwise, the object is zero-initialized.

B() is a value-initialization of temporary which will be used in copy-initialization of b1.

In B b2 there is no initializer specified for an object, so according to C++03 Standard 8.5/9:

If no initializer is specified for an object, and the object is of (possibly cv-qualified) non-POD class type (or array thereof), the object shall be default-initialized; if the object is of const-qualified type, the underlying class type shall have a user-declared default constructor. Otherwise, if no initializer is specified for a non-static object, the object and its subobjects, if any, have an indeterminate initial value; if the object or any of its subobjects are of const-qualified type, the program is ill-formed.

To get zeros for b2 you could write B b2 = {};.

like image 124
Kirill V. Lyadvinsky Avatar answered Oct 04 '22 23:10

Kirill V. Lyadvinsky


In both cases, this statement defines b1 and copy-intializes it from a value-initialized temporary B object.

B b1 = B();

When B doesn't have a user-declared constructor, value-initializing causes call of B's members to be value-initalized, and for simple types, such as int, this means zero-initializing.

When B does have a user-declared constructor, value-initializing tries to call the default constructor. If the members x and y are not listed in the constructor initializer list, then they are left uninitialized.

B b2;

In functions, local objects of POD-type without an initializer are left uninitialized. When you don't define a constructor for B, it is a POD-class so this applies and the values of b2.x and b2.y have indeterminate values.

If the object is of non-POD class type, then it is default-initialized, but if this calls a constructor which leaves its members uninitialized then this makes no difference.

like image 42
CB Bailey Avatar answered Oct 04 '22 22:10

CB Bailey


This is value-initialization versus no initialization. If you write

B b1 = B();

you get copy-initialization with a "value-initialized" temporary -- B(). Value-initialization of class-type objects invokes a user-defined constructor (if existant) or otherwise value-initializes the members. Value-initialization of scalar type objects is equivalent to zero-initialization. When you declare your own constructor that doesn't do anything, your scalar members are not initialized.

B b1;

is a default-initialization or no initialization at all (depending on B).

The exact initialization rules are rather complicated. See C++ standard section 8.5 "Initializers".

like image 27
sellibitze Avatar answered Oct 04 '22 22:10

sellibitze