范围内的范围,做或不做?

时间:2012-08-23 21:40:52

标签: c++ scope dos-donts

虽然下面的例子编译得很好,除了最后一行有错误,我想知道范围内这个'范围'的来龙去脉?也是这个术语,如果有的话。

考虑这些括号:

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

修改 Accepted answer来自bitmask,但我认为每个人都应将其置于anio answer的背景下。特别是,引用:“也许你应该将你的功能分解为两个功能”

5 个答案:

答案 0 :(得分:7)

<强>不要即可。无论如何!

将数据尽可能保持在本地并尽可能保持const有两个主要优点:

  • 副作用减少,代码变得更加功能
  • 对于复杂的对象,只要不再需要数据,就可以在函数内提前调用析构函数

此外,这对于文档总结函数的特定部分所做的工作非常有用。

我听说这被称为显式或虚拟范围

答案 1 :(得分:6)

我个人认为在函数中添加额外的作用域并没有多大价值。如果您依靠它来分离函数的各个部分,也许您应该将函数分解为2个函数。较小的功能比较大的功能更好。你应该努力使用易于理解的小功能。

函数中范围的合法使用是限制锁定的持续时间:

int doX() 
{

 // Do some work

  { 
  //Acquire lock


  } // Lock automatically released because of RAII
}

内部范围有效地限制了锁定的代码。我相信这是常见的做法。

答案 2 :(得分: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();
}

答案 3 :(得分:3)

显式范围通常不会用于评论目的,但如果您觉得它使您的代码更具可读性,我认为这样做没有任何损害。

典型用法是avoiding name clashes and controlling when the destructors are called

答案 4 :(得分:2)

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