范围定义括号和堆栈?

时间:2010-08-27 15:33:20

标签: scope

我刚读过这个问题:Why are different case condition bodies not in different scope?

这是一个Java问题,但我的问题同时适用于C#和Java(以及具有此范围缩减功能的任何其他语言)。

在这个问题中,OP谈到了他如何知道他可以手动添加{}来改进交换机中每个案例的范围。我的问题是,这是如何工作的?它是否像方法调用一样上升到堆栈?如果是这样,它做了什么使它仍然可以访问在此范围之前声明的其他变量?

4 个答案:

答案 0 :(得分:3)

所有它正在做的是定义另一个范围,它没有被转换为方法调用。请记住,对于本地人来说,CLR / JVM可能决定不为它们使用堆栈空间,它可以选择使用处理器寄存器。在某些情况下,如果您原谅双关语,它可以决定通过不需要它们来优化一些当地人。它甚至可以决定它可以为多个变量使用一个寄存器或“堆栈上”的内存位置,因为它们永远不会重叠。

以相关问题为例:

switch(condition) {
  case CONDITION_ONE: {
    int account = 27373;
  }
  case CONDITION_TWO: {
    // account var not needed here
  }
  case CONDITION_THREE: {
    // account var not needed here
  }
  case CONDITION_FOUR: {
    int account = 90384;
  }
}

目前,该代码在功能上与:

相同
int account;

switch(condition) {
  case CONDITION_ONE: {
    account = 27373;
  }
  case CONDITION_TWO: {
    // account var not needed here
  }
  case CONDITION_THREE: {
    // account var not needed here
  }
  case CONDITION_FOUR: {
    account = 90384;
  }
}

由于account变量从未在多种情况下使用,这意味着它是在内存中使用寄存器或单个空间的理想候选者(在此简单示例中)。

答案 1 :(得分:2)

范围由编译器在编译时定义。它对变量的实际内存布局几乎没有影响。因此,如果我写:

func()
{ 
    int a;
    {
      int b;
    }
    {
      int c;
    }
}

编译器可以选择创建三个变量,并在函数开头为所有三个变量分配空间,或者它可以为两个变量分配空间,并为b&角

范围只是编译器知道何时不再需要变量。究竟它对这些信息的作用是它的业务。

答案 2 :(得分:1)

  

我的问题是,这是如何运作的?它是否像方法调用一样上升到堆栈中?

它就像用于创建新本地范围的任何其他{}一样工作。这之间的范围没有区别:

void foo() {
    {
        int a = 123;
    }
    // a is gone here
    {
        // different a
        float a = 12.3f;
    }
}

和此:

void foo() {
    switch (123) {
    case 1:
        {
            int a = 123;
        }
        // a is gone here
        break;

    case 2:
        {
            // different a
            float a = 12.3f;
        }
    }
}
  

如果是这样,它做了什么,以便它仍然可以访问在此范围之前声明的其他变量?

块始终可以访问其外部作用域,或者这不起作用:

void foo() {
    int a = 123;
    if (true) {
        a = 345; // accessing a in outer scope
    }
}

答案 3 :(得分:0)

在范围内声明的任何变量只能在该范围内以及其中的任何范围内访问。因此,在函数中,您可以在许多编程语言中使用{}来创建在离开该范围时将被破坏的变量。

此外,使用switch而不使用范围时可能会出现问题,正如这段C代码所示:

int main() {
  int foo = 4;
  int bar = getbar(); // getbar() is a function returning an integer
  switch(bar)
  {
    case 1:
      int abc = 6;
      break;
    case 2:
      int abc = 7; // compiler error: 'abc' was defined twice in this scope
      break;
  }
}
int abc = 147; // This is no error, as 'abc' fell out of scope when
// leaving the `switch` statement

正如您所看到的,abc已在switch的范围内声明了两次,这会导致错误。这很容易被修复为给每个case自己的变量范围:

int main() {
  int foo = 4;
  int bar = getbar(); // getbar() is a function returning an integer
  switch(bar)
  {
    case 1:
    {
      int abc = 6;
      break;
    }
    case 2:
    {
      int abc = 7; // no more errors, since these declarations will destruct when
      // falling out of scope
      break;
    }
  }
}
int abc = 147; // This is no error, as 'abc' fell out of scope when
// leaving the `switch` statement