【问题标题】:Difference between local scope and function scope局部作用域和函数作用域的区别
【发布时间】:2011-10-28 19:19:19
【问题描述】:

一旦我认为这两者具有相同的含义,但在阅读了更多关于它的信息后,我仍然不清楚它们之间的区别。本地范围有时不是指功能范围吗? 只有标签才有函数作用域是什么意思?

【问题讨论】:

  • 在 C++03 中有时称为“局部作用域”,有时称为“块作用域”,现在在 C++11 中到处都称为“块作用域”。少一个混乱的来源!

标签: c++ scope


【解决方案1】:
void doSomething()
{                                    <-------
     {                   <----               | 
                              |              |
         int a;           Local Scope    Function Scope
                              |              |
     }                   <----               | 
}                                    <------- 

函数作用域在外部{}之间。

本地范围在内部{}之间

请注意,{``} 创建的任何作用域都可以作为本地作用域调用,而函数体开头的 {``} 创建函数作用域。
因此,有时局部作用域可以与函数作用域相同。

只有标签才有函数作用域是什么意思?

Labels 只是标识符后跟一个冒号。带标签的语句用作goto 语句的目标。标签可以在它们出现的函数中的任何地方使用,但不能在函数体之外引用。因此,它们被称为具有函数作用域。

代码示例:

int doSomething(int x, int y, int z)
{
     label:  x += (y + z);   /*  label has function scope*/
     if (x > 1) 
         goto label;
}

int doSomethingMore(int a, int b, int c)
{
     if (a > 1) 
         goto label; /*  illegal jump to undefined label */
}

【讨论】:

    【解决方案2】:

    本地范围是 { 和它正在关闭的 } 之间的区域。函数作用域是一个函数的开始 { 和它的结束 } 之间的区域,它可能包含更多的“本地”作用域。标签在定义它的整个函数中都是可见的,例如

    int f( int a ) 
    {
        int b = 8;
        if ( a > 14 )
        {
           int c = 50;
           label:
           return c - a - b;
        }
        if ( a > 7 ) goto label;
        return -99;
    }
    

    int c 在其封闭块之外不可见。标签在其封闭块之外可见,但仅对函数范围可见。

    【讨论】:

    • 我一直认为标签具有全局范围。函数范围更加健全。
    • 如果标签有全局作用域,你可以从一个函数体跳到另一个函数体,这太疯狂了。
    • 不,@Rob,如果语言还允许非本地 goto,您只能从一个函数跳转到另一个函数。不过,它们不一定是一揽子交易。具有全局标签名称的仅限本地 goto 仅意味着您在为标签选择名称时必须小心,以免它们干扰程序中其他地方的标签,就像为预处理器宏选择名称时一样。
    • 很好的说明。如果没有伴随非本地 goto,具有全局范围 /really/ 的标签名称将毫无意义。正如你所说,那只是命名空间污染。
    【解决方案3】:

    局部作用域有时不是指函数作用域吗?

    是的。在大多数 C 派生语言中,变量在声明它们的范围内有效。如果您在函数内声明变量,但不在任何其他代码块内,则该变量通常称为“本地”或“自动”变量。您可以在函数中的任何位置引用它。另一方面,如果你在另一个代码块中声明你的变量——比如说,在条件语句的主体中,那么变量只在那个代码块内有效。这里的其他几个答案给出了很好的例子。

    只有标签才有函数作用域是什么意思?

    上下文会有所帮助,但这意味着您不能从一个函数跳转到另一个函数中的标签。

    void foo(int a) {
        if (a == 0) goto here;  // okay -- 'here' is inside this function
        printf("a is not zero\n");
        goto there;             // not okay -- 'there' is not inside this function
    here:
        return;
    }
    
    void bar(int b) {
        if (b == 0) goto there; // okay -- 'there' is in this function
        printf("b is not zero\n");
    there:
        return;
    }
    

    不要挑起马蜂窝,但标签的范围可能不会经常出现。标签主要与 goto 语句一起使用,如果有的话,很少需要,即使您确实选择使用 goto,您也可能不会考虑尝试跳入不同的函数。

    【讨论】:

    • 具有讽刺意味的是,C 没有本地作用域,只有函数作用域 AFAIK。
    【解决方案4】:

    函数作用域略大于函数作用域body:函数参数在外部作用域,而局部变量只在内部作用域。这在函数尝试块中最为明显:

    void f(int a) try {
      // function body
    } catch(...) {
      // catch block
    }
    

    在catch块内,只有函数作用域内的变量还在作用域内,局部变量不存在。

    当然,您可以并且确实也一直在引入更深层次的嵌套作用域,例如在for 循环体或条件体中。

    【讨论】:

    • +1 我过去写过很多 C++,但我从未见过这种结构。
    • @Caleb:你可能想看看this
    • @Caleb:想象一下将它用于构造函数......然后忘记立即使用它:-)
    • @KerrekSB:这让我想知道我可能还错过了什么,但我不确定我真的想知道。
    【解决方案5】:
    bool m[3][3];
    void f1()
    {
      int i;
      // redefining a variable with the same name in the same scope isn't possible
      //int i; //error C2086: 'int i' : redefinition
    }
    
    void f2()
    {
      int i; // ok, same name as the i in f1(), different function scope.
    
      {
        int i; // ok, same name as the i above, but different local scope.
      }
    
      // the scope if the following i is local to the for loop, so it's ok, too.
      for (int i = 0; i < 3; i++)
      {
        for (int j = 0; j < 3; j++)
        {
          if (m[i][j])
            goto loopExit;
        }
      }
    loopExit:
      std::cout << "done checking m";
    // redefining a label with the same name in the same function isn't possible
    // loopExit:; // error C2045: 'loopExit' : label redefined
    }
    
    void f3()
    {
    loopExit:; // ok, same label name as in f2(), but different function scope
    }
    

    【讨论】:

      猜你喜欢
      • 2015-08-22
      • 2014-03-20
      • 2013-04-17
      • 1970-01-01
      • 1970-01-01
      • 2011-05-09
      • 1970-01-01
      • 1970-01-01
      • 2012-05-02
      相关资源
      最近更新 更多