3

尽管下面的示例编译得很好,除了最后一行有错误,我想知道这个“范围”在一个范围内的来龙去脉?还有这个的术语,如果有的话。

考虑这些括号:

void func()
{

    int i = 0;

    { // nice comment to describe this scope

        while( i < 10 )
            ++i;

    }

    { // nice comment to describe this scope

        int j= 0;
        while( j< 10 )
            ++j;

    }

    i = 0; // OK
    // j = 0; // error C2065

}

考虑一下:

error C2065: 'j' : undeclared identifier

编辑: 接受的答案来自bitmask,尽管我认为每个人都应该将它放在anio 's answer的上下文中。特别是,引用:“也许你应该把你的功能分成两个功能”

4

5 回答 5

7

。无论如何!

将数据保持在尽可能本地和尽可能常量有两个主要优点:

  • 副作用减少,代码变得更实用
  • 对于复杂的对象,只要不再需要数据,就可以在函数中尽早调用析构函数

此外,这对于文档总结功能的特定部分所做的工作很有用。

我听说这被称为显式或虚拟作用域

于 2012-08-23T21:45:28.367 回答
6

我个人认为在函数中添加额外的范围没有太大价值。如果您依赖它来分隔函数的各个部分,也许您应该将函数分解为 2 个函数。较小的功能优于较大的功能。您应该努力拥有易于理解的小功能。

在函数中使用范围的一种合法用途是限制锁的持续时间:

int doX() 
{

 // Do some work

  { 
  //Acquire lock


  } // Lock automatically released because of RAII
}

内部作用域有效地限制了持有锁的代码。我相信这是普遍的做法。

于 2012-08-23T21:45:38.193 回答
4

是的,绝对 - 始终保持变量尽可能本地化是一个好习惯!一些例子:

for (std::string line; std::getline(std::cin, line); )     // does not
{                                                          // leak "line"
    // process "line"                                      // into ambient
}                                                          // scope

int result;

{                                        // putting this in a separate scope
    int a = foo();                       // allows us to copy/paste the entire
    a += 3;                              // block without worrying about
    int b = bar(a);                      // repeated declarators
    result *= (a + 2*b);
}

{                                        // ...and we never really needed
    int a = foo();                       // a and b outside of this anyway!
    a += 3;
    int b = bar(a);
    result *= (a + 2*b);
}

有时同步需要范围,并且您希望使关键部分尽可能短:

int global_counter = 0;
std::mutex gctr_mx;

void I_run_many_times_concurrently()
{
    int a = expensive_computation();

    {
        std::lock_guard<std::mutex> _(gctr_mx);
        global_counter += a;
    }

    expensive_cleanup();
}
于 2012-08-23T22:00:10.223 回答
3

显式作用域通常不是为了注释目的而进行的,但是如果您觉得这样做会使您的代码更具可读性,我认为这样做没有任何害处。

典型用法是避免名称冲突并控制何时调用析构函数

于 2012-08-23T21:46:29.373 回答
2

一对花括号定义了一个范围。在一个范围内声明或定义的名称在该范围外是不可见的,这就是为什么j最后没有定义的原因。如果作用域中的名称与之前定义的名称相同并且在该作用域之外,它会隐藏外部名称。

于 2012-08-23T21:48:39.350 回答