全局变量何时被认为是良好/推荐的做法?

时间:2013-08-31 11:35:57

标签: c++ c global-variables

我一直在阅读很多关于为什么全局变量是坏的以及为什么不应该使用它们的原因。然而,大多数常用的编程语言都以某种方式支持全局变量。

所以我的问题是,仍然需要全局变量的原因是什么,它们是否提供了一些无法实现的独特且不可替代的优势?与用户指定的自定义间接相比,从本地范围中检索对象时,全局寻址是否有任何好处?

据我了解,在现代编程语言中,全局寻址与计算内存地址的每个偏移量具有相同的性能损失,无论它是否是从"全局"用户内存或来自this或任何其他指针的偏移量。因此,就性能而言,用户可以在使用公共指针间接所需的狭窄情况下伪造全局变量,而不会损失实际全局变量的性能。还有什么?真的需要全局变量吗?

6 个答案:

答案 0 :(得分:9)

全局变量通常不是很糟糕,因为它们的性能,它们很糟糕,因为在规模很大的程序中,它们很难将所有内容封装起来 - 有信息“泄漏”,这往往使得很难弄清楚会发生什么上。

基本上,变量的范围应该只是代码所需的工作和相对容易理解的内容,而不是更多。将程序中的全局变量打印出十二倍的表是可以管理的,将它们放在一个数百万行的会计程序中并不是那么好。

答案 1 :(得分:4)

全球变量意味着全球状态。这使得无法存储程序中给定部件或功能的本地重叠状态。

例如,让我们将给定用户的凭据存储在整个程序中使用的全局变量中。现在升级我们的程序以同时允许多个用户将变得更加困难。如果我们只是将用户的状态作为参数传递给我们的函数,那么升级到多个用户的问题就会少得多。

答案 2 :(得分:3)

我认为这是另一个与goto类似的主题 - 它是一种“宗教事物”。

有很多方法可以“解决”全局变量,但是如果你仍然在代码中的不同位置访问相同的内存,则可能会出现问题。

全局变量对某些事情很有用,但绝对应该“谨慎”使用(比goto更多,因为滥用的范围更大)。

有两件事使全局变量成为问题:  1.很难理解变量的作用。  2.在多线程环境中,如果从一个线程写入全局并由任何其他线程读取,则需要某种同步。

但有时全局变量非常有用。例如,拥有一个config变量,该变量包含来自应用程序配置文件的所有配置值。另一种方法是将它存储在一个从一个函数传递到另一个函数的对象中,而这只是额外的工作而不会带来任何好处。特别是如果配置变量是只读的。

但是,作为一个整体,我建议避免使用全局变量。

答案 3 :(得分:1)

  

我的问题是仍然需要全局变量的原因,

有时您需要从许多不同的功能中访问相同的数据。这是你需要全局的时候。

例如,我正在研究一段代码,看起来像这样:

static runtime_thread *t0;

void 
queue_thread (runtime_thread *newt)
{
   t0 = newt;
   do_something_else ();
}

void 
kill_and_replace_thread (runtime_thread *newt)
{
   t0->status = dead;
   t0 = newt;
   t0->status = runnable;
   do_something_else ();
}

注意:将上面的内容作为某种混合C和伪代码,让您了解全局实际有用的地方。

答案 4 :(得分:0)

在编写任何跨平台库时,Static Global几乎是必需的。这些全局变量是静态的,因此它们保留在翻译单元中。几乎没有跨平台库不使用静态全局变量,因为它们必须向用户隐藏其特定于平台的实现。这些特定于平台的实现保存在静态全局变量中。当然,如果他们使用不透明的指针并要求将特定于平台的实现保存在这种结构中,则可以创建一个没有任何静态全局变量的跨平台库。但是,此类对象需要传递给此类库中的所有函数。因此,您可以在任何地方传递此不透明指针,或制作静态全局变量。

还有标识符限制问题。编译器(尤其是较旧的编译器)对范围内可处理的标识符数量有限制。许多操作系统仍然使用大量的#define而不是enum级,因为它们的旧编译器无法处理膨胀其标识符的枚举常量。适当地重写头文件可以解决其中的一些问题。

答案 5 :(得分:-1)

当您想在包括main在内的每个函数中使用全局变量时,会考虑全局变量。还要记住,如果全局初始化变量,其初始值在每个函数中都是相同的,但是您可以在函数内重新初始化它,以便在该函数中为该变量使用不同的值。这样,您不必在每个函数中反复声明相同的变量。但是,他们有时可能会造成麻烦。

  • 列表项

全球各地都有名字。当您认为使用本地

时,您可能会在不知不觉中最终使用全局
  • 如果你在声明一个全局变量时犯了错误,那么你必须将更改应用到整个程序,就像你不小心将它声明为int而不是float