我已经阅读了关于范围的内容,并且认为我到目前为止已经理解了它 . 我遇到了另一个程序的问题,在尝试修复它时,我发现循环范围内的变量表现得非常不符合我的预期 . 所以我做了这个程序来表明我的意思:
#include <iostream>
using namespace std;
int main()
{
int num = 6;
for (int i = 0; i < 5; i++)
{
cout << num;
int num = 5;
cout << num;
}
}
我期望首次运行for循环,第一个cout << num将是未定义的,因为它是一个新的范围,而num尚未定义 . 但相反,它只使用了前一个范围的num值 . 然后当num在循环内部初始化为5时,之后,num的所有输出都应为5.但输出为656565 ...
因此,使用这些信息,我 Build 了一个模型,我认为变量的范围是如此工作,它看起来像这样:
所以在图像中你可以看到我认为范围是如何工作的,我认为对于循环中的每次迭代,循环获得一个新的变量范围,然后在循环结束时删除它的范围并获得一个新的范围 . 下一次迭代的开始,解释为什么for循环使用前一个范围中的num,直到num在当前范围内重新初始化 . 我的理解是否正确?
3 回答
如果范围1是最外部范围,范围4是最内部范围,则图表是正确的 . 您对"overwritten"这个词的使用不是C的惯例 . 变量不会被覆盖,而是shadowed . 类似的阴影是许多编程语言的一部分 .
您在此处的理解不正确,您看到的输出是正确的 .
在循环内,第一个
cout << num
将打印在循环之前定义的变量num
. 第二个将打印循环内定义的变量 .循环中的
int num = 5
不会影响先前定义的变量(在外部作用域中) . 它定义了一个全新的变量,并将其初始化为5
. 对循环之前定义的num
的值没有任何影响 . 因此,外部定义的num
将保留值6
,内部定义的值(在每次循环迭代中创建)将具有值5
. 虽然你的代码给它们起了相同的名字(num
),但它们是完全不同的变量,并且在内存中占用不同的地址 - 所以改变一个不会改变另一个 .实际上你的代码
在概念上等同于
这种概念等价来自标准中的要求,如果在块中创建自动存储持续时间的多个变量,则它们不再以其构造顺序的相反顺序存在 . (即,如果跟踪类对象的构造函数和析构函数的调用,则最先构造的自动存储持续时间对象将首先被破坏) .
除非
cout
语句位于当前作用域或包含作用域中,否则它们不能访问num
的值 . 因此,以这种方式查看意味着第一个cout << num
仅具有外部num
(初始化为6
的那个)而不是内部的可见性 . 而第二个cout << num
访问内部范围中定义的变量 .是的,但
num
已重新初始化_727842 . 它定义了另一个变量 ."inner"
num
shadows "outer"num
.由于
num
都具有块范围,因此basic.scope.block: