我应该显式地定义变量的作用域吗?

Should I explicitely scope variables?

本文关键字:作用域 变量 定义 我应该      更新时间:2023-10-16

这更像是一个风格问题,因为我知道在实践中大多数编译器可能会优化以提供相同的效果,但我一直在阅读,通常情况下,您应该始终在使用它们的范围内声明/定义变量。因此,在不能内联声明的情况下,例如下面的代码片段,我考虑将索引变量包含在作用域括号中(花括号,不确定在这种情况下您叫它们什么),以便显式地限制这些变量的作用域。这是好的做法吗?如果有,请解释一下原因。

{
    size_t i = 0; // this variable has no use outside of the range-based for loop
    for (auto const input : input_vector)
    {
        neuron_sequence[i].ForceSignal(input);
        ++i;
    }
}

这当然是一个很好的做法。它清楚地限制了变量的使用范围。我经常这样做。像这样的作用域也被用来强制运行一些对象析构函数。

例如:

std::vector<int> v;
v.resize( 10 ); // now holds memory for 10 ints

如何清理内存?没有函数可以调用,也没有任何方法可以手动告诉向量v清理其内存。一个解决方案是强制它离开作用域(假设我正确地使用了swap):

std::vector<int> v;
v.resize( 10 ); // now holds memory for 10 ints
{
  std::vector<int> temp;
  temp.swap( v );
} // temp goes out of scope and clears the memory that v used to hold

另一个常见的用法是在开关箱中。我经常需要在switch中创建一个临时变量:

switch( val )
{
case constant:
  {
    int x = 10;
    // ... do stuff
  }
}

我能想到的最后一个地方是为某种代码编写测试用例的时候。当进行单元测试时,我经常只是想在不花费太多开发时间的情况下尽可能快地编写测试代码。因此,我将一堆相关的测试放在一个函数中,但将局部变量包装在单独的作用域中,以确保不会碰到任何奇怪的bug(可能通过测试共享迭代器)。

是的,你应该明确地作用域变量:

  1. 作用域定义了局部变量的生命周期,所以适当地限定变量的作用域意味着变量只有在它们满足所需的使用时才有效。不要只是活着和占用内存。
  2. 在同名变量的情况下,局部变量隐藏或遮蔽同名全局变量。因此,显式设置作用域可以提高读者的可读性。(至少我感觉如此)

对于像整数这样的小数据类型,你真的不需要担心这个问题,因为正如你所说,编译器将根据变量的活性以及它是否到达某个位置来优化代码。在这种情况下,这更多的是一个风格问题。我建议不要经常这样做,因为代码的可读性和易维护性也是和性能一样重要的因素。

但是对于复杂类型,像这样限制生命周期是有用的。例如,对于一个内部分配大量内存的向量,如果它的作用域像这样有限,这可以节省一些空间。

  • 当您发现自己关心对象的生命周期时(通常是因为使用的内存/资源,或者希望防止意外或促进故意重用相同的标识符),紧作用域是好的
    • 。执行一些重复的操作——甚至可能使用宏替换——在需要临时的地方,但是更改名称没有特别的目的,而且很繁琐
  • 你不能总是这样做:你会遇到很多情况,适合一个变量的最紧凑的范围与另一个变量的范围重叠:例如,试图在{ X a = 1; X b(a, 2); ++a; } ++b;中"范围"a过早地破坏b
  • 在某些情况下,创建大量的小作用域会大大增加源代码,使其更难以直观地吸收和维护。要检查引入的作用域是否有一个控制if/for/while语句,这需要一些脑力劳动,而且很难一眼看到整个函数流。当然,减少函数中剩余变量的数量也可以减少脑力劳动——所以这是一种平衡行为。

总的来说,有选择性的选择是好的,但你会对什么时候有必要产生一种感觉。如果不确定,可能不重要。