在C++ 中类的初始化会调用构造函数,根据构造函数来初始化类的变量。如果某个变量没有初始化,则该变量的值是一个随机值。
结构体的初始化,是根据所给值来初始化的,如果结构中某个变量的没有赋值,那么该变量被赋值为0.
简单的例子:
Demo1:
#include<iostream>
using namespace std;
struct T
{
int a,b;
char szName[20];
};
int main()
{
struct T t = {1};
cout<<t.a<<endl<<t.b<<endl<<t.szName<<endl;
return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
猜一下输出结果吧,很容易就是1,0
那么类呢?
Demo2:
#include<iostream>
using namespace std;
class T
{
public:
T(){};
~T(){};
int a,b;
char szName[20];
};
int main()
{
T t ;
cout<<t.a<<endl<<t.b<<endl<<t.szName<<endl;
return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
答案也能猜到吧!就是一堆乱码==.
这些很简单,但当一个结构体里面含有类或者结构体呢,结果会怎么样呢?
类的成员该是什么呢,是空还是乱码?
Demo3:
#include<iostream>
using namespace std;
class OldMan
{
public:
OldMan(){};
~OldMan(){};
char szName[10];
};
struct Man
{
char szName[20] ;
};
void test()
{
struct s {int a ,b ;char nNum[10]; OldMan oldm; Man man;};
s t={1};
cout<<t.a<<endl<<t.b<<endl<<t.nNum<<endl
<<t.oldm.szName<<endl<<t.man.szName<<endl;
};
int _tmain(int argc, _TCHAR* argv[])
{
test();
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
输出是什么呢?能猜到吗?答案等会告诉你,你先猜吧。
如果类中含有结构体,而此时类的构造函数却又没有任何初始化的操作呢?答案又是什么样的?
Demo4:
#include<iostream>
using namespace std;
struct Beer
{
int a,b;
char szName[20];
};
class Man
{
public:
Man(){};
~Man(){};
char szName[20];
Beer br;
};
int main()
{
Man m;
cout<<m.szName<<endl<<m.br.a<<endl<<m.br.b<<m.br.szName<<endl;
return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
答案是什么。。。
看下面,4个Demo运行的结果吧:
Demo1:
Demo2:
Demo3:
Demo4:
看来结构的初始化,本着结构体内得所有成员都初始化的原则,进本数据类型就是零,而结构体内类的成员就会调用它本身的构造函数来初始化。
类的初始化很简单就是按照构造函数初始化,编译器没有添加任何构造函数之外的操作。
我说你就信?^_^ 不能哦,我们还是要事实来说话,所以分析一下汇编代码吧,看看编译器是不是按照以上原则来编译Demo的,这里就分析Demo3吧!因为他很具有代表性,其他你自己来!
首先在test()处设置断点后,进入test()函数内部,查看汇编代码:
首先对于函数压栈的初始化我们就不看了,
看区域1:这是对变量a,b,nNum的初始化过程可以看到直接进行赋值操作
mov: * *
而区域2中却是调用call指令:
call OldMan::OldMan(01111087h)
来初始化成员 oldm
下面的 mov 是初始化 man的。ok了。编译器确实是按照上面说的原则做的,这些Demo我在两个编译器上做了实现与查看汇编,汇编的代码不一样,但原理一样的。
看完你似乎懂了
但不要忘记初始化结构体哦,要不就会这样:
Demo5:
#include<iostream>
using namespace std;
struct T
{
int a,b;
char szName[20];
};
int main()
{
struct T t ;
cout<<t.a<<endl<<t.b<<endl<<t.szName<<endl;
return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
结果就是乱码了: