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"的错误。 但是,它可以成功构建并且可以毫无问题地进行调试。 为什么?
-
这个相关的问题可能会引起关注。
-
您应该尽可能避免使用,它不是C ++标准的一部分(Linux上不存在)。
-
好的,谢谢你的建议。 getch()和getche()的任何替代选择? 我正在使用.NET Framework
-
我可以使用cin来固定屏幕,但是getch()是否有专门用于字符输入的替代方法?
-
都不使用。 它不由您的程序来管理其运行所在的终端(在这种情况下)。
自动变量(例如cube)的范围是在其内声明的块。声明cube的块是for循环的主体。在每次迭代结束时,cube变量超出范围,下一次迭代开始,然后再次将cube引入范围。从逻辑上讲,没有冲突是因为同一范围内不存在两个标识符cube-实际上,只有一个声明cube。
可能有必要在变量声明与由于该声明而创建对象之间进行区分。只有一个声明int cube = ...;。这段代码可以被多次访问并不重要;它仍然只是一个声明。语言规则说,您不能在同一个作用域中声明两个具有相同名称的变量,但这没关系,因为您只声明了一次。这是编译器能够分析的完全静态的规则。
碰巧的是,由于您的for循环,声明到达了10次,这意味着将创建10个int对象。由于变量的范围,它们将不会同时存在。这不是程序的静态属性。编译器通常无法预先知道一行代码将被执行多少次。
-
我使用监视窗口来跟踪变量。每当程序的控制重新进入循环体时,在到达语句int cube = numbnumbnumb之前就已经知道了变量cube。
-
因此,据我所知,尽管立方体在每次迭代结束时都会消失,但是当重新进入物体时它会自动重新建立。因此,在体内故意定义多维数据集应该给出错误,不是吗?
-
@ user3296146我在答案中添加了更多内容。如果在同一作用域中有两个int cube声明,则会收到错误消息。
-
您使用了术语"自动变量"。这是什么意思?
-
@ user3296146用于引用引入具有自动存储持续时间的对象的变量。自动对象将在其作用域的末端自动销毁。备用存储期限为动态,静态和线程。
-
@JosephMansfield谢谢!我想我明白了,尽管我仍然需要进一步思考:)另外,您说在每次迭代中都会创建变量的新对象。新对象是在内存中的相同或不同位置创建的吗?
-
@ user3296146这不是语言指定的,但是任何明智的编译器都只会为对象重用相同的存储位置。
-
@Spook当然!我沉迷于约瑟夫的答案,我忘了自己可以自己查一下。
-
@JosephMansfield好吧!总体而言,我的意思是!病态的思考,如果我感到困惑,请在这里发表不适的评论:)
-
@ user3296146当然,此循环可能在其他许多函数foo中,该函数在许多地方都被调用。在不同的foo调用中,cube对象可以放置在各种不同的存储位置。我只是说,在循环的单个迭代集中引入的每个对象都可能具有相同的内存位置。
第二次进入循环时,第一个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变量。
-
您说:"因此,实际上,循环的每个迭代都将具有其全新的新鲜多维数据集变量"。但是我使用了监视窗口,并且每次重新进入循环主体时,监视窗口都会在到达该行之前显示多维数据集(int cube = numbnumbnumb;),并且该值也具有与上一次迭代相同的值。
-
@ user3296146允许编译器优化这些事情,只要所生成的代码的行为就像已按所述声明了变量一样即可。由于您的代码没有明显的副作用,因此没有理由不进行优化。您可能想对带有构造函数和析构函数的更复杂的对象重复该实验。
变量cube仅在for循环的主体内使用。我不确定说它被声明了十次是正确的(声明,实际上是您的定义,是源代码的语法和静态文本部分)。
在C ++中,您可以(并且经常这样做)使用带有局部变量的块。 cube的范围从其声明开始,并在包含块的末尾(括号{ ... })结束。
如果已定义变量的类型具有构造函数,则在定义点调用它。如果该类型具有析构函数,则在概念上在块末尾调用它(例如,在结束} ....之前)。
-
我喜欢您使用"构造函数"和"析构函数"进行解释的方式。它巩固了我对这些术语的理解,并从不同的角度回答了我的问题。
-
它肯定会声明一次,因为声明是指源代码,而不是运行时。我想,可以说,它实例化了十次(自动,在堆栈上)。
该变量将在循环的每次迭代中声明,然后在块({...})结束时超出范围,即它将不再存在。然后在下一次迭代中将再次声明,这不是重新声明,因为它不存在。据说这是一个"局部变量",在这种情况下是局部的。
由于cube是在循环主体中定义的,因此其范围将是该主体。因此,每次迭代完成后,cube将超出范围,并且在下一次迭代中将创建一个全新的cube。理论上就是这样。尽管编译器会优化此代码并且仅创建一个变量,但可能会发生。无论哪种方式,代码都是完全有效的,并且可以按例外方式工作。
在每次迭代中都声明并定义了变量" cube"。"多维数据集"的作用域随着迭代而死,并且在每个循环中都会发生新的声明和定义。