撇开这个观点是否正确的问题,当使用全局变量时会出现哪些客观优缺点?
全局变量的问题在于,由于每个函数都可以访问这些变量,因此越来越难以确定哪些函数实际上读取和写入这些变量。
为了理解应用程序的工作原理,你几乎必须考虑修改全局状态的每个函数。这是可以做到的,但随着应用程序的增长,这将变得越来越困难,甚至是完全无法做到的(或者至少是浪费时间)。
如果你不依赖全局变量,可以根据需要在不同函数之间传递状态。这样你就有更好的机会理解每个函数的功能,因为你不需要考虑全局状态。
我的教授曾经说过类似这样的话:如果你正确使用全局变量,那么使用它们是可以的。但我不认为我擅长正确使用它们,所以我很少使用它们。
static
全局变量,编程语言是C。由于限制在相对较小的翻译单元内,它们开始类似于C++对象的类变量。 - Vorac程序生命周期,文件作用域变量
。一旦将指向变量的指针传递到外部世界(这在自动变量中是不可能的),它们就变得非常全局。 - Vorac当全局变量(例如结构体)的源代码被修改时,所有使用它的内容都必须重新编译,以便使用该变量的所有内容都知道其真实大小和内存模板。
如果有多个组件可以修改全局变量,则可能会遇到不一致的数据存在于全局变量中的问题。在多线程应用程序中,您可能需要添加某种锁定或关键区域,以提供一种方式,使只有一个线程可以同时修改全局变量,并且当线程正在修改变量时,所有更改都已完成并提交,然后其他线程才能查询变量或修改它。
调试使用全局变量的多线程应用程序可能更加困难。您可能会遇到竞态条件,这可能会导致难以复制的缺陷。通过全局变量进行通信的几个组件,特别是在多线程应用程序中,了解哪个组件何时以及如何更改变量,可能非常难以理解。
全局变量的使用可能会导致名称冲突问题。与全局变量同名的局部变量会隐藏全局变量。在使用C编程语言时,还会遇到命名约定的问题。解决方法是将系统划分为子系统,并以相同的前三个字母开头为特定子系统的全局变量命名(请参阅解决Objective-C中名称空间冲突)。C++提供了命名空间,而在C中,可以创建一个全局可见的结构体,其中成员是各种数据项和指向数据和函数的指针,这些数据和函数在文件中作为静态提供,因此仅具有文件可见性,只能通过全局可见的结构体引用。namespace
和 C 的 struct
技术
对于C++编程语言,namespace
指令有助于减少名称冲突的可能性。 namespace
与class
和各种访问关键字(private
,protected
和public
)一起提供了大部分封装变量所需的工具。然而,C编程语言没有提供此指令。这个stackoverflow帖子,Namespaces in C ,提供了一些C语言技术。struct
,并且在这个struct
中有指向各种全局变量和函数的指针。使用static
关键字将全局变量的实际定义给予文件范围。如果您使用const
关键字指示哪些是只读的,编译器可以帮助您强制执行只读访问。struct
技术也可以封装全局变量,使其成为一种包或组件,恰好是一个全局变量。通过拥有这种类型的组件,更容易管理影响全局变量和使用全局变量的功能的更改。
然而,虽然namespace
或struct
技术可以帮助管理名称冲突,但全局变量引入的组件间耦合问题仍然存在,特别是在现代多线程应用程序中。
全局变量只有在没有其他选择时才应使用。是的,这包括单例模式。90%的情况下,引入全局变量是为了节省传递参数的成本。然后多线程/单元测试/维护编码发生,你就会遇到问题。
所以,在90%的情况下,全局变量都是不好的。异常情况可能不会在你的大学年代看到。我能想到的一个例外是处理固有全局对象,例如中断表。像DB连接这样的东西似乎是全局的,但实际上并不是。
是的,但只有当你停止使用全局变量的代码并开始编写使用该代码的其他内容时,才会产生全局变量的成本。但成本仍然存在。
换句话说,这是一种长期间接成本,因此大多数人认为它并不糟糕。
全局变量和你对它们的使用一样糟糕,没有更少。
如果你正在创建一个完全封装的程序,你可以使用全局变量。 使用全局变量是个“罪”,但编程上的罪大部分都是哲学层面的。
如果你查看L.in.oleum,你会发现这种语言的变量仅为全局变量。 这是不可扩展的,因为所有的库都别无选择,只能使用全局变量。
也就是说,如果你有选择,并且可以忽略程序员的哲学,全局变量并不是那么糟糕。
如果正确使用,Gotos也不是坏事。
最大的“坏”问题是,如果你用错了,人们会尖叫,火星着陆器会坠毁,世界会爆炸...或者类似于这样的事情会发生。
天哪,我打赌那些开发人员后悔使用了全局变量!两项研究都发现了代码风格上的一些问题。评论人员关注的样式问题之一是广泛使用未受保护的全局变量。这被认为是不良形式,因为它增加了程序状态变得不一致或值被意外修改或覆盖的风险。研究人员还对代码中未始终保持小数精度表示出一些担忧。
extern
,以便将它们的使用限制在需要访问它们的编译单元中。如果你的代码依赖于大量全局变量,但每个编译单元只需要访问其中一小部分,则可以考虑将它们分类到多个源文件中,以便更容易地限制每个文件对全局变量的访问。它们是好是坏取决于如何使用它们。大多数人倾向于使用它们不良,因此对它们持谨慎态度。如果使用得当,它们可以成为一个巨大的福音;然而,如果使用不当,它们肯定会在最不期望的时间和方式咬你一口。
一个好的方法是把它们看作不坏,但它们会导致糟糕的设计,并且可以将糟糕的设计效果成倍增加。
即使你不打算使用它们,了解如何安全使用它们并选择不使用,也比因为不知道如何安全使用它们而不使用更好。如果你发现自己需要维护依赖全局变量的预先存在的代码,如果不知道如何正确使用它们,可能会遇到困难。
g_module_varNameStyle
完全可读。明确一点,如果可以轻松避免使用全局变量,我就不会使用它们 - 关键词是“轻松”,因为自从我停止相信必须以任何代价避免它们 - 或者更确切地说是混淆它们 - 以来,我的编码体验更好了,我的代码也(惊人!)更整洁。 - underscore_d我会用另一个问题来回答这个问题:你是否使用单例模式?单例模式是坏的吗?
因为(几乎所有)单例的使用都是对全局变量的美化。
单例模式仅适用于愿意将代码组织好并限制数据访问的人
。每天都会出现糟糕的代码,而全局变量使情况更糟。 - Ruan Mendes