首页 文章

我想确认我对变量范围的理解在C中是正确的

提问于
浏览
3

我已经阅读了关于范围的内容,并且认为我到目前为止已经理解了它 . 我遇到了另一个程序的问题,在尝试修复它时,我发现循环范围内的变量表现得非常不符合我的预期 . 所以我做了这个程序来表明我的意思:

#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 了一个模型,我认为变量的范围是如此工作,它看起来像这样:

Scope Diagram

所以在图像中你可以看到我认为范围是如何工作的,我认为对于循环中的每次迭代,循环获得一个新的变量范围,然后在循环结束时删除它的范围并获得一个新的范围 . 下一次迭代的开始,解释为什么for循环使用前一个范围中的num,直到num在当前范围内重新初始化 . 我的理解是否正确?

3 回答

  • 4

    如果范围1是最外部范围,范围4是最内部范围,则图表是正确的 . 您对"overwritten"这个词的使用不是C的惯例 . 变量不会被覆盖,而是shadowed . 类似的阴影是许多编程语言的一部分 .

  • 1

    我期望首次运行for循环,第一个cout << num将是未定义的,因为它是一个新范围,而num尚未定义 . 但相反,它只使用了前一个范围的num值 . 然后当num在循环内部初始化为5时,之后,num的所有输出都应为5.但输出为656565 ...

    您在此处的理解不正确,您看到的输出是正确的 .

    在循环内,第一个 cout << num 将打印在循环之前定义的变量 num . 第二个将打印循环内定义的变量 .

    循环中的 int num = 5 不会影响先前定义的变量(在外部作用域中) . 它定义了一个全新的变量,并将其初始化为 5 . 对循环之前定义的 num 的值没有任何影响 . 因此,外部定义的 num 将保留值 6 ,内部定义的值(在每次循环迭代中创建)将具有值 5 . 虽然你的代码给它们起了相同的名字( num ),但它们是完全不同的变量,并且在内存中占用不同的地址 - 所以改变一个不会改变另一个 .

    实际上你的代码

    int num = 6;
    for(int i = 0; i <5; i)
    {
    cout << num;
    int num = 5;
    cout << num;
    }

    在概念上等同于

    int num = 6;
    for (int i = 0; i < 5; i++)
    {
        cout << num;
        {                   //  note another scope introduced here
            int num = 5;
            cout << num;
        }
    }
    

    这种概念等价来自标准中的要求,如果在块中创建自动存储持续时间的多个变量,则它们不再以其构造顺序的相反顺序存在 . (即,如果跟踪类对象的构造函数和析构函数的调用,则最先构造的自动存储持续时间对象将首先被破坏) .

    除非 cout 语句位于当前作用域或包含作用域中,否则它们不能访问 num 的值 . 因此,以这种方式查看意味着第一个 cout << num 仅具有外部 num (初始化为 6 的那个)而不是内部的可见性 . 而第二个 cout << num 访问内部范围中定义的变量 .

  • 1

    我的理解是否正确?

    是的,但 num 已重新初始化_727842 . 它定义了另一个变量 .
    "inner" num shadows "outer" num .

    由于 num 都具有块范围,因此basic.scope.block

    块中声明的名称是该块的本地名称;它有块范围 . 它的潜在范围从其声明点开始,并在其块结束时结束 . 在块作用域中声明的变量是局部变量 .

    int main() {
       int num = 6; // block scope (a) ---- point of declaration for (a) begins
       for (int i = 0; i < 5; i++)
       {
          cout << num; // uses (a)
          int num = 5; // block scope (b) ---- point of declaration for (b) begins
          cout << num; // uses (b)         ||
       }               //                 ---- (b) goes out of scope here
    } // ---- (a) goes out of scope here
    

相关问题