Reputation: 15631
There is this code:
#include <iostream>
class KlasaNiePOD{
public:
int a;
~KlasaNiePOD(){}
};
int main() {
KlasaNiePOD obiekt1; // first case
std::cout << obiekt1.a << std::endl; // -1075234152
KlasaNiePOD obiekt2 = KlasaNiePOD(); // second case
std::cout << obiekt2.a << std::endl; // 0
return 0;
}
Why in the first case 'a' is not initialized, but in second case it is? Shouldn't be called constructor always in non-POD classes?
Edit:
Fragment from assembly:
.globl main
.type main, @function
main:
.LFB960:
.cfi_startproc
.cfi_personality 0x0,__gxx_personality_v0
.cfi_lsda 0x0,.LLSDA960
pushl %ebp
.cfi_def_cfa_offset 8
movl %esp, %ebp
.cfi_offset 5, -8
.cfi_def_cfa_register 5
andl $-16, %esp
pushl %esi
pushl %ebx
subl $40, %esp
movl 28(%esp), %eax
movl %eax, 4(%esp)
movl $_ZSt4cout, (%esp) # std::cout << obiekt1.a << std::endl;
.LEHB0:
.cfi_escape 0x10,0x3,0x7,0x55,0x9,0xf0,0x1a,0x9,0xf8,0x22
.cfi_escape 0x10,0x6,0x7,0x55,0x9,0xf0,0x1a,0x9,0xfc,0x22
call _ZNSolsEi
movl $_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_, 4(%esp)
movl %eax, (%esp)
call _ZNSolsEPFRSoS_E
.LEHE0:
movl $0, 24(%esp) # Here obiekt2.a = 0
movl 24(%esp), %eax
movl %eax, 4(%esp)
movl $_ZSt4cout, (%esp) # std::cout << obiekt2.a << std::endl;
.LEHB1:
call _ZNSolsEi
movl $_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_, 4(%esp)
movl %eax, (%esp)
call _ZNSolsEPFRSoS_E
.LEHE1:
movl $0, %ebx
leal 24(%esp), %eax
movl %eax, (%esp)
call _ZN11KlasaNiePODD1Ev
leal 28(%esp), %eax
movl %eax, (%esp)
call _ZN11KlasaNiePODD1Ev
movl %ebx, %eax
addl $40, %esp
popl %ebx
popl %esi
movl %ebp, %esp
popl %ebp
ret
Upvotes: 1
Views: 330
Reputation: 16046
ISO 14882:2011(e) 8.5.1 :
An aggregate is an array or a class (Clause 9) with no user-provided constructors (12.1), no brace-or-equalinitializers for non-static data members (9.2), no private or protected non-static data members (Clause 11), no base classes (Clause 10), and no virtual functions (10.3).
As such, your class is an aggregate.
KlasaNiePOD obiekt2 = KlasaNiePOD(); // second case
will invoke aggregate and finally value initialization, causing the int to be zero intialized.
Add
KlasaNiePOD(){}
to your class definition, and you will see that the setting to 0 will vanish (as this will make it not an aggregate anymore).
Upvotes: 1
Reputation: 153977
The standard defines several different types of initialization,
depending on context. Zero-initialization sets all of the members to 0
(converted to the appropriate type, so pointers will be set to a null
pointer value, even if the null pointer isn't all zero bits); no
constructor is called. Default-initialization calls the default
constructor, which be default doesn't do anything. Value-initialization
calls the default constructor if a user defined constructor is present,
but does zero-initialization, followed by the default constructor, if
there is no user defined constructor. An object whose initializer is
simply ()
(an empty list) is value-initialized. An object with static
lifetime is zero-initialized before program start (always); if it has a
non-trivial constructor, its constructor will be called sometime later
(but before entering main
). All other objects defined with no
initializer are default-initialized.
In your code, obiekt1
is default-initialized; in this case, a no-op
(leaving the members uninitialized). obiekt2
is initialized by copy
of a value-initialized temporary; the value-initialization sets a
to
0. (The actual copy may be optimized out, with the value-initialization
taking place directly on the object.)
Upvotes: 3
Reputation: 254631
KlasaNiePOD obiekt1; // first case
This is default-initialised; since it doesn't have a default constructor, members with a fundamental type (which includes numeric types) are left uninitialised.
KlasaNiePOD obiekt2 = KlasaNiePOD(); // second case
The temporary KlasaNiePOD()
is value-initialised; since it doesn't have a default constructor, members with a numeric type are initialised to zero.
Upvotes: 5