虽然如此,但是现在的C++编译器通常像C编译器一样,在一个程序块的开头就分配好所有变量的内存。这一切对于程序员来说是透明的,因为我们的变量在定义之前总是无法得到存储空间,即便编译器这么干了!
即使存储空间在一开始就被分配了,但是C++对象的构造函数仍然需要到对象定义的时候才会被调用,因为标识符只有到此时才是有效的。编译器为了防止程序员用一些条件选择手段跳过变量的初始化就开始使用,它会检查代码中是否把一个变量对象的定义放到了条件块中,比如switch的case块,goto等,看下面这段代码:http://www.90168.org/
1 #include <iostream>
2 #include <string>
3
4 using namespace std;
5
6 class A{
7 public:
8 //A(){} //对于VC2005和GCC来说,只有提供构造函数,编译器才会检测出错误
9 int b;
10 };
11
12 int main()
13 {
14 int i;
15 cin>>i;
16
17 if (i < 10)
18 goto flag;
19
20 A fsd; //构造函数的调用被goto跳过
21 fsd.b = i;
22
23 flag:
24 switch (i)
25 {
26 case 1:
27 A a;
28 a.b = 3;
29 break;
30 case 10:
31 {
32 A aa;
33 aa.b = 10;
34 cout<<a.b<<endl; //error C2360: initialization of 'a' is skipped by 'case' label
35 break;
36 }
37 default:
38 break;
39 }
40
41 cout<<fsd.b<<endl;//如果输入参数小于10,那么fsd的初始化将被跳过,程序运行到这里崩溃
42
43 return 0;
44 }
输入1,跳过了fsd的初始化,程序运行结果不可知。2 #include <string>
3
4 using namespace std;
5
6 class A{
7 public:
8 //A(){} //对于VC2005和GCC来说,只有提供构造函数,编译器才会检测出错误
9 int b;
10 };
11
12 int main()
13 {
14 int i;
15 cin>>i;
16
17 if (i < 10)
18 goto flag;
19
20 A fsd; //构造函数的调用被goto跳过
21 fsd.b = i;
22
23 flag:
24 switch (i)
25 {
26 case 1:
27 A a;
28 a.b = 3;
29 break;
30 case 10:
31 {
32 A aa;
33 aa.b = 10;
34 cout<<a.b<<endl; //error C2360: initialization of 'a' is skipped by 'case' label
35 break;
36 }
37 default:
38 break;
39 }
40
41 cout<<fsd.b<<endl;//如果输入参数小于10,那么fsd的初始化将被跳过,程序运行到这里崩溃
42
43 return 0;
44 }
输入10,跳过了a的初始化,程序运行结果同样不可知。