有这段代码:
#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;
}
为什么在第一种情况下'a'没有被初始化,但在第二种情况下它是?不应该总是在非POD类中调用构造函数?
编辑:
汇编片段:
.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
答案 0 :(得分:5)
KlasaNiePOD obiekt1; // first case
这是默认初始化;因为它没有默认构造函数,所以具有基本类型(包括数字类型)的成员将保持未初始化状态。
KlasaNiePOD obiekt2 = KlasaNiePOD(); // second case
临时KlasaNiePOD()
值初始化;因为它没有默认构造函数,所以具有数字类型的成员初始化为零。
答案 1 :(得分:3)
该标准定义了几种不同类型的初始化,
取决于具体情况。零初始化将所有成员设置为0
(转换为适当的类型,因此指针将设置为null
指针值,即使空指针不是全零位);没有
构造函数被调用。默认初始化调用默认值
构造函数,默认情况下不执行任何操作。值初始化
如果存在用户定义的构造函数,则调用默认构造函数,
但是进行零初始化,然后是默认构造函数if
没有用户定义的构造函数。初始值为的对象
简单地()
(空列表)是值初始化的。具有静态的对象
在程序启动之前,生命周期是零初始化(总是);如果它有
非平凡的构造函数,它的构造函数将在稍后调用
(但在输入main
之前)。用no定义的所有其他对象
初始化程序是默认初始化的。
在您的代码中,obiekt1
是默认初始化的;在这种情况下,一个无操作
(让成员未初始化)。 obiekt2
由副本初始化
价值初始化临时;值初始化将a
设置为
0.(可以使用值初始化优化实际副本
直接发生在物体上。)
答案 2 :(得分:1)
ISO 14882:2011(e)8.5.1:
聚合是一个没有用户提供的数组或类(第9条) 构造函数(12.1),非静态数据没有大括号或相等的初始化 成员(9.2),没有私有或受保护的非静态数据成员(条款 11),没有基类(第10条),也没有虚函数(10.3)。
因此,您的班级是聚合。
KlasaNiePOD obiekt2 = KlasaNiePOD(); // second case
将调用聚合和最终值初始化,导致int初始化为零。
添加
KlasaNiePOD(){}
到您的类定义,您将看到设置为0将消失(因为这将使它不再是聚合)。