TA的每日心情 | 慵懒 2018-3-28 17:24 |
---|
签到天数: 276 天 连续签到: 1 天 [LV.8]以坛为家I
|
初始化 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是一个全局性的变量,它的生命周期,从程序开始,直到结束,都是有效的.所以它在整BPOSThttp://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.
|
评分
-
查看全部评分
|