考虑一些代码:
#include <iostream>
int main()
{
using std::cout;
int a=3;
cout << "a="<<a<<"\n";
{
int a=a;
cout << "new a = " << a << "\n";
a=5;
cout << "a = " << a << "\n";
}
cout << "old a = " << a << "\n";
}
我希望它能打印
a=3
new a = 3
changed a = 5
old a = 3
但我得到的实际上似乎在第二行说new a = 0
。我认为它会像类的构造函数中的初始化列表一样工作,其中可以像
C::C(int a) : a(a) {}
但由于某种原因,这是不同的。首先,完全删除外部代码不会导致编译错误。所以我假设int a=a;
是有效的。打开所有编译器警告会导致:
test.cpp: In function ‘int main()’:
test.cpp:10:15: warning: ‘a’ is used uninitialized in this function
int a=a;
现在我的问题是:为什么这种语法有效?为什么编译器不会说“未定义变量a”?
答案 0 :(得分:11)
它在语法上是有效的,因为变量的声明点在其初始化之前,并且该名称在该点之后的任何地方都可用。这样可以减少像
这样的狡猾的初始化void *p = &p;
合法地使用被初始化的变量的名称(但不是值)。
它的行为无效,因为使用未初始化对象的值会产生未定义的行为。这不是一个需要诊断的错误(因为,一般来说,分析程序流以查看对象是否已初始化可能很困难或不可能),但正如您所指出的,许多编译器会发出警告像这样直截了当的案例。