为什么c++编译器接受这种初始化?静态int x=x

Why is this initialization accepted by the c++ compiler? static int x = x;

本文关键字:静态 int 初始化 编译器 c++ 为什么      更新时间:2023-10-16

我刚刚发现了这个:

static int x = x;

为什么C++编译器接受这种初始化?

我会称之为编译器异常,但有人可能会对此做出很好的解释。

因此,对于具有静态存储的数据,可以用自身初始化变量。。。我已经在VS2015和VS2017编译器以及其他一些在线C++编译器中尝试过这一点。

对于static和非static变量,它实际上是相同的。

名称在其声明符之后以及初始化之前(如果有的话)立即可见。因此在中

static int x = x;

名称x在其第一次出现之后立即变得可见并且可以在初始化器中被引用。由于它是静态的,所以它的初始值定义得很好(它是0)。

即使在区块范围内,这也是合法的:

int x = x;

尽管在这里您可能会收到警告,因为x正在使用其自己的不确定值进行初始化(在大多数情况下,行为是未定义的)。

这是一件愚蠢的事情,但C++并不是为了阻止你做愚蠢的事情。例如,您可能想要声明一个指向自身的指针:

void *p = (void*)&p;

这里的初始值设定项指的是p的地址,而不是它的值,但名称p必须是可见的才能起作用。添加一条特殊情况规则被认为是不值得的。

如果你想禁止C++中所有愚蠢的构造(当然还有C),你会得到一个很长的列表。

与C相比,C++实际上是一种非常不同的语言,但它仍然有其根源。而且,至少在一开始,对与C兼容的关注是非常强烈的。即使在今天,C++标准也包含了用于此目的的C头。

许多奇怪的事情都可以追溯到C语言,而C语言对编译器的要求很低,但对程序员的要求更高。许多构造产生未定义的行为不确定的值。这主要有两个原因。首先,它使正确编写编译器变得更容易,并且对系统的要求更低。这在C的早期很重要。这种语言出现在1972年,也就是Commodore发布具有4kB内存的家用电脑VIC-20的8年前。其次,它允许编译器以更少的内存使用率生成更快的代码,正如刚才提到的,这在过去非常重要。

因此,即使根本没有任何有效的用例(即使我看不到它,我也不排除它可能存在的可能性),也没有足够的理由对此采取行动

正如Keith在回答中提到的,如果变量是静态的,那么它的值将为0,这意味着该值不是不确定的。static int x = x;的结果是完全清楚的,为什么禁止它呢?你会让C++规范变得更大、更难维护,并可能破坏一些旧代码,只是为了解决一些不成问题的问题。

当涉及到非静态变量时,这是另一回事,因为值是不确定的。这里有一个更好的理由来禁止这个构造,但另一方面,你已经收到了警告。至少如果你正在使用-Wall,你应该这样做。我还可以补充一点,许多警告都是警告,而不是错误,只是为了不破坏旧代码。但是,与其禁止初始化本身,不如完全禁止使用未初始化的变量。