为什么单独初始化一个新变量是有效的?

7

考虑下面的代码:

#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 functionint main()’:
test.cpp:10:15: warning: ‘a’ is used uninitialized in this function
         int a=a;

那么我的问题是:为什么这种语法是有效的呢?为什么编译器不会说类似于“未定义变量a”的话呢?


1
@101010 啊嗯? - Borgleader
@ShafikYaghmour 如果您将此作为答案发布,并附上简短的摘要,您将获得一些投票,这个问题也可以被标记为已回答。 - Björn Pollex
1
@BjörnPollex 这是一个重复的问题,非常接近我发布的第二个链接,但可能还有更接近的重复问题,但无论如何都应该将其关闭为重复。 - Shafik Yaghmour
1个回答

13

这是在语法上有效的,因为变量的声明点在其初始化之前,而且在那个点之后该名称随处可用。这允许更少的不可靠初始化,例如

void *p = &p;

在初始化变量时,该代码合法地使用了变量的名称(但不使用变量的值)。

这种行为在行为上是无效的,因为使用未初始化对象的值会产生未定义的行为。这不是需要诊断的错误(因为通常很难或不可能分析程序流以查看对象是否已初始化),但正如您所指出的,许多编译器会针对像这样的简单情况发出警告。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接