Reputation: 7585
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.
Upvotes: 5
Views: 6358
Reputation: 21898
The O's are explained by Kirill
The other value:-858993460 is 0xCCCCCCCC, which is the default value for uninitialized stack memory in VC's debug builds.
Uninitialized heap memory defaults to 0xCDCDCDCD. And of course, in release builds, the default contents is random.
Now, I have to admit that I didn't know it's legal to call a c'tor directly as you do in your example! And I would have sweared that this is illegal...
Upvotes: 2
Reputation: 6516
i tried on vc6 and Visual Studio 2005 i am getting below result in both:Could you please post disassemble code generated , Like below i have posted disassemble code for 2005
x:-858993460
y:-858993460
x:-858993460
y:-858993460
B b1 = B(); //init1
0043DEDE lea ecx,[b1]
0043DEE1 call B::B (43ADD9h)
B b2; //init2
0043DEE6 lea ecx,[b2]
0043DEE9 call B::B (43ADD9h)
print(b1);
0043DEEE lea eax,[b1]
0043DEF1 push eax
0043DEF2 call print (43A302h)
0043DEF7 add esp,4
print(b2);
0043DEFA lea eax,[b2]
0043DEFD push eax
0043DEFE call print (43A302h)
0043DF03 add esp,4
Upvotes: 0
Reputation: 99725
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 = {};
.
Upvotes: 10
Reputation: 793299
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.
Upvotes: 5
Reputation: 28127
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".
Upvotes: 3