为什么这个C++代码在不应该工作的时候工作?



我正在使用Robert Lafore的书学习C++(OOP with C++)。在书中,我遇到过这样一个例子:

#include <iostream>
#include <conio.h>
using namespace std;
void main ()
{
int numb;
for ( numb = 1 ; numb <= 10 ; numb++ )
{
cout << setw(4) << numb;
int cube = numb*numb*numb;
cout << setw(6) << cube << endl;
}
getch();
}

变量"cube"已在循环体内部声明为int。

int cube = numb*numb*numb;

由于循环迭代10次,因此变量"cube"也将被声明10次无论进行何种迭代,都可以在循环体内部访问"cube"。因此,当我们为第二次迭代输入循环体时,"cube"已经是已知的(因为它已经在第一次迭代中声明了),而另一个"cube’"的声明应该会给出"重新定义"的错误。但相反,它成功地构建并调试没有问题。为什么?

自动变量(如cube)的作用域是在其中声明它的块。在其中声明cube的块是for循环的主体。在每次迭代结束时,cube变量超出范围,下一次迭代开始,然后cube再次引入范围。从逻辑上讲,没有冲突,因为在同一范围内不存在两个标识符cube——事实上,只有cube的一个声明。

可能值得区分变量的声明和由于该声明而创建的对象。只有一个声明int cube = ...;。这段代码可能被多次访问并不重要;它仍然只是一个声明。该语言的规则规定,不能在同一范围内声明两个名称相同的变量,但这没关系,因为只声明一次。这是一个完全静态的规则,编译器可以对其进行分析。

恰好由于for循环,您的声明达到了10次,这意味着将创建10个int对象。由于变量的范围,它们不会同时存在。这不是程序的静态属性。编译器通常无法事先知道一行代码将被访问多少次。

当您第二次进入循环时,第一个cube已经超出范围,所以一切正常。

两个cubes在同一范围内将是一个问题:

{
int cube = 0;
int cube = 1;
}

您发现了"自动存储持续时间"。

变量cube在循环内部声明。尤其是在循环的块范围内。在循环结束时,该变量将被销毁,就像在任何块作用域中声明的任何变量一样,无论是函数、循环、if/else块,还是可以使用{}在代码中任何地方声明的原始块作用域,即:

int main(){
//Beginning of block
{
int cube = 1;
//cube exists and is declared here
}//End of block
//cube is gone here
return 0;
}

因此,实际上,循环的每一次迭代都会有其全新的cube变量。

变量cube仅在for循环的内部使用。我不确定说它被声明了十次是否正确(声明,在您的情况下实际上是定义,是源代码的语法和静态文本部分)。

在C++中,你可以(而且你经常这样做)拥有带有局部变量的块。cube的作用域从it声明开始,到包含块的末尾结束(大括号{})。

如果定义变量的类型有构造函数,则在定义点调用它。如果该类型有一个析构函数,它在概念上会在块的末尾被调用(象征性地,就在关闭}之前……)

变量将在循环的每次迭代中声明,然后随着块({...})的结束,它将超出范围,即它将不存在。然后在下一次迭代中,它将被再次声明,这不是重新声明,因为它不存在。据说它是一个"局部变量",在这种情况下是块的局部变量。

由于cube是在循环主体内定义的,其范围将是该主体。因此,在每次迭代完成后,cube将超出范围,在下一次迭代中,将创建一个全新的cube。理论上就是这样。不过,编译器可能会优化此代码,并且只创建一个变量。无论哪种方式,代码都是完全有效的,并且将正常工作。

在每次迭代中声明和定义变量"cube"。"cube"的作用域随着迭代而消亡,每个循环中都会出现新的声明和定义。

最新更新