关于调试:为什么这个C ++代码不应该工作?

Why is this C++ code WORKING when it SHOULDN'T?

我正在使用Robert Lafore的书(C ++的OOP)学习C ++。
在书中,我遇到了以下示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#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。

1
int cube = numb*numb*numb;

由于循环迭代10次,因此变量" cube"也将声明10次。 无论迭代如何,都可以在循环体内访问"多维数据集"。 因此,当我们进入循环主体进行第二次迭代时," cube"是已知的(因为它已经在第一次迭代中声明了),而另一个" cube"的声明应该给出" redefinition"的错误。 但是,它可以成功构建并且可以毫无问题地进行调试。 为什么?


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

可能有必要在变量声明与由于该声明而创建对象之间进行区分。只有一个声明int cube = ...;。这段代码可以被多次访问并不重要;它仍然只是一个声明。语言规则说,您不能在同一个作用域中声明两个具有相同名称的变量,但这没关系,因为您只声明了一次。这是编译器能够分析的完全静态的规则。

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


第二次进入循环时,第一个cube已超出范围,因此一切正常。

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

1
2
3
4
{
    int cube = 0;
    int cube = 1;
}


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

变量cube在循环内部声明。特别是在循环的块范围内。在循环结束时,此变量将被销毁,就像在任何块范围内声明的任何变量一样,它可以是函数,循环,if / else块,也可以是可以在其中的任何位置声明的原始块范围。使用{}的代码,即:

1
2
3
4
5
6
7
8
9
10
11
12
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的范围从其声明开始,并在包含块的末尾(括号{ ... })结束。

如果已定义变量的类型具有构造函数,则在定义点调用它。如果该类型具有析构函数,则在概念上在块末尾调用它(例如,在结束} ....之前)。


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


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


在每次迭代中都声明并定义了变量" cube"。"多维数据集"的作用域随着迭代而死,并且在每个循环中都会发生新的声明和定义。