[声明] 此发言乃杂家杂谈,我姑且写之,你姑且看之.如你有什么不同见解,我有什么错误,请指出. 一切来人来函来电,均谢绝之. :)
初始化 VS 赋值 当你写下如下语句:
<1> int x = 1; <2> int x; x = 1; 它们之间可有什么区别?
有.这是两个不同的动作. <1>是一个初始化操作,而<2>是一个赋值操作.前者是一个编译器动作,而后者是一个程序动作.
需要证据?好的,看下面的程序.
<3> int main(void) { static int val0 = 0x55; int val1 = 0x66; int val2; val2 = 0x77; } 进入调试状态,在main处停下.此时main()函数尚未执行,但val0的值已经准备妥当. 就像前面所说的, val0是一个初始化动作, 编译器在进入main()函数之前就将val0初始化完毕.
喔,等等.val1不也是一个初始化动作吗,那怎么它的值没有准备好.
是的,val1仍然是一个初始化动作.不过,唔,你知道的,局部变量有点特殊,它位于堆栈中. 从某些方面说,它具有overlay属性,所以在每次进入main()函数后(不是在之前),都需要将它初始化一次.
或者换一种说法,更好理解: val1是一个全局性的变量,它的生命周期,从程序开始,直到结束,都是有效的.所以它在整BPOSThttps://bbs.21ic.com/club/bbs/SaveOwnerEdC中,只需要初始化一次就好. 而val2是一个局部性的变量,它的生命周期,从它声明开始,到它所在的函数退出前那一刻.所以每次这个函数被调用,它都将被初始化一次. 虽然,从汇编后的结果看来,val1和val2操作的汇编代码是相同的,但它们仍然是2个不同的动作(操作).它们的汇编代码之所以相同,那是因为你使用的是内置的数据类型(int),如果你尝试在C++下写类似的代码(看程序片断<7>),那就是另一个故事了.
杂项: 1) const 变量不能通过赋值动作获得一个值(废话),但可以通过初始化动作获得一个初值(还是废话). <3> const int x0 = 5; //ok const int x1; x1 = 5; //error
2) 关于struct <4> typedef struct S{int v1, int v2}; S s0 = {1,2}; //ok, 初始化 S s1; s1 = {1,2}; //error, 不能这样赋值 3) 某种意义上,初始化动作是一个一次性的动作. 你一定写过类似下面的程序: <5> foo(..) { static int cnt = 0; cnt ++; //..... } 你也一定不会粗心的写成如下程序: <6> foo(..) { static int cnt; cnt = 0; cnt ++; //..... } 因为程序<5>是一个初始化操作,是一次性的动作. 而程序<6)是一个赋值操作,foo()每被调用,cnt将重新被赋值,这不是你要的结果,是不? 这再次说明:初始化操作是编译器动作,而赋值操作不是. 4) 效率 在C中,通常都是使用一些编译器内置的数据类型,你不大可能看到初始化动作和赋值动作的效率,也因此你不太容易看到它们之间的巨大区别. 但是如果在C++中,你就能看到初始化和赋值是多么的不同了. <7> class X {....}; X xx; X xx0 = xx; //初始化动作,它使用copy construtor直接初始化对象. X xx1; //声明一个对象,对象获得内存,并调用default construtor初始化对象. xx1 = xx; //使用operator= 将对象xx的值赋给xx1. |