全局变量不好吗?[关闭]


247

在C / C ++中,全局变量是否如我的教授所认为的那么糟糕?


17
万一他试图开个玩笑,我会咬……“他们有多糟糕”?
Zach Scrivena 09年

13
我认为这个问题很有趣!自开始以来,软件开发仍面临着同样的陷阱,程序员通常仍然不知道使用全局变量,gotos,简称变量不是问题。每天都会编写错误代码,而无需使用它们。+1
西尔文·罗德里格

69
我们怎么可能回答?他没有告诉我们他的教授认为他们有多糟糕。:)
史蒂夫·福洛斯

9
@Juan Mendes我100%同意您的意见!我正在谈论的问题是,许多开发人员知道他们不应该使用全局变量,但是他们只是不知道为什么!因此,我看到了许多大型软件,其中每个函数都具有包含100个字段的相同大型结构-妈妈,没有全局变量!与所谓的“良好实践”相同的问题:它们是在某些情况下(而不是在所有情况下)的良好做法。使用它们可能会创建无法维护的代码。干杯。
西尔文·罗德里格

3
全局变量很少有很好的用途。一个可能但值得商use的用途是全局“配置”对象,该对象在启动时会读取一次配置文件。
西勒(Siler)

Answers:


256

全局变量的问题在于,由于每个函数都可以访问这些变量,因此越来越难弄清哪个函数实际读写这些变量。

要了解应用程序的工作方式,您几乎必须考虑修改全局状态的每个函数。可以做到,但是随着应用程序的增长,它将变得越来越困难,甚至几乎不可能(或者至少浪费时间)。

如果不依赖全局变量,则可以根据需要在不同函数之间传递状态。这样一来,您就更有机会了解每个功能的作用,因为您无需考虑全局状态。


9
这个答案真的很好。与“最小化变量的作用域的回答结合这stackoverflow.com/questions/357187/...
bobobobo

17
将“类”替换为“应用程序”,将“对象状态”替换为“全局状态”,并且您为不使用类中的成员变量(也称为字段)提供了完全相同的参数。真正的答案是在适当时使用它们。
伊恩·高德比

2
几个(也许很愚蠢)的问题:1)如果您想知道哪个函数可以读写这些变量,难道您不可以仅使用编辑器中的“ find”函数来发现修改这些变量值的情况吗?2)“那是可以做到的,...完全浪费时间)。” 能给我举个例子吗?3)“如果您不依赖于全局变量,则...您无需考虑全局状态。” 我不明白那是什么优势。也许一个例子对我有用。
Andrei 2013年

2
@bobobobo断开的链接,我们可以从10k以上的用户处获取屏幕截图吗?
noɥʇʎԀʎzɐɹƆ

3
@noɥʇʎԀʎzɐɹƆ,您在这里!i.imgur.com/RwRgJLZ.jpg
Mateen Ulhaq,

85

重要的是要记住总体目标:清晰度

之所以有“无全局变量”规则,是因为大多数时候,全局变量会使代码的含义不清楚。

但是,就像许多规则一样,人们会记住该规则,而不是该规则的意图。

我看到过这样的程序,它们通过传递大量的参数来避免全局变量的危害,似乎使代码的大小增加了一倍。最后,使用全局变量会使程序对于阅读该程序的人更加清晰。通过漫不经心地遵守规则一词,原始的程序员未能遵守规则的意图。

因此,是的,全局变量通常很糟糕。但是,如果您最终觉得,使用全局变量可以使程序员的意图更加清楚,那么请继续。但是,请记住,当您强迫某人访问第二段代码(全局变量)以了解第一段代码的工作原理时,清晰度会自动下降。


8
建议使用全局变量而不是传递变量是使代码不可重用且对多线程不安全的秘诀
Juan Mendes

16
在适当的情况下建议全局变量是编写更清晰,性能更高的代码的秘诀。“传递”需要不断的堆栈动态内存分配,这对于应该是全局的东西(例如用于传入套接字数据的全局缓冲区)来说是愚蠢的。例如,如果您有一个读取Winsock recv()的函数,为什么在每次调用中不断创建和取消分配此缓冲区?使缓冲区成为全局缓冲区。无论如何,多个线程不会读取它。
詹姆斯,

很好奇,哪个程序通过传递参数以避免全局变量来使代码大小加倍?以我的经验,使用全局变量可能会解决数据公开问题,但是通常需要添加其他复杂逻辑,以确保这些神奇变量的行为正确。
user2167582 '18

3
如果某人传递了约100个变量,那么他们还没有了解对象是什么。在最坏的情况下,使用对该对象的引用会绕过指针。我要说的规则不仅是清晰度,而且还有可测试性-使用非全局性的趋向于使事情更容易测试。
UKMonkey

2
“如果某人传递了约100个变量,那么他们就不会了解对象是什么。” 同意,但并非所有世界都是面向对象的。我个人将代码大小加倍的示例是大约1986年的大型Fortran程序。作为刚从大学毕业的新员工,我通过为每个调用添加大约30个参数来“改进”它,从而消除了所有全局变量。然后,当我意识到自己所做的事情时,就束手无策了。
汤姆·韦斯特

64

我的教授曾经说过类似的话:如果正确使用全局变量就可以了。我认为我从来都不擅长正确使用它们,因此我很少使用它们。


25
如此真实。它们就像gotos,如果您不知道何时使用它们,那就永远不要。
David Holm,2009年

5
在我目前的公司中,它们static大量使用全局变量,语言是C。由于局限于相对较小的翻译单元,它们开始类似于C ++对象的类变量。
Vorac 2014年

1
@Vorac静态变量不是全局变量,它们是局部变量。全局变量是程序中任何地方都可用的变量(因此为“ global”,duh)。不要与文件范围变量混淆,文件范围变量是在任何函数外部声明的变量。静态文件作用域变量不是全局变量。
隆丁

1
为了纠正自己,program lifetime, file scope variables。而一旦你传递一个指针变量对外部世界(这是不可能的自动变量),他们变得相当全球..
Vorac

@Lundin我同意,static全局变量的作用域仅限于同一翻译单元。但是它们的生存期直到程序结束都是任何全局变量。
akhilesh1988 '16

38

仅在没有其他选择时才应使用全局变量。是的,包括Singletons。90%的时间引入了全局变量,以节省传递参数的成本。然后发生多线程/单元测试/维护编码,您遇到了问题。

所以是的,在90%的情况下,全局变量都是错误的。您在大学期间不太可能看到例外。我可以想到的一个例外是处理诸如中断表之类的固有全局对象。诸如DB连接之类的事情似乎是全球性的,但并非如此。


2
在大学时代看到的一个例外是图形回调函数。在XWindows中,鼠标回调没有void *数据参数,该参数使您可以传递程序状态的任意块……(但这并不比全局方法要好得多)……
Brian Postow

10
+1表示“类似DB连接的东西似乎是全局的,但不是全局的。”
R .. GitHub停止帮助ICE,2010年

1
中断表不是全局的,每个处理器只有一个-但是每个处理器也有一个程序实例,因此它“被取消”。
user253751 '18

1
谁能给我启发一下为什么数据库连接不是全局的(还有什么很好的替代方法)?我一直认为联系是可以接受全局变量的罕见情况之一。
Floella

33

全局变量为程序员创建的问题是,它扩展了正在使用全局变量的各个组件之间的组件间耦合表面。这意味着随着使用全局变量的组件数量增加,交互的复杂性也会增加。这种增加的耦合通常使进行更改时更容易将缺陷注入系统,也使缺陷更难以诊断和纠正。这种增加的耦合还可以减少进行更改时可用选项的数量,并且可以增加更改所需的工作量,因为通常必须跟踪也使用全局变量的各个模块才能确定更改的后果。

封装的目的与使用全局变量基本相反,它的目的是减少耦合,以使对源的理解和更改更容易,更安全,更容易测试。当不使用全局变量时,使用单元测试要容易得多。

例如,如果您有一个简单的全局整数变量被用作枚举指示符,表明各种组件都用作状态机,然后通过为新组件添加新状态来进行更改,则必须跟踪所有其他组件确保更改不会影响它们的组件。一个可能的问题的示例是,如果在各个地方都使用了一个switch语句来测试枚举全局变量的值以及case每个当前值的语句,并且这种情况发生在某些switch语句没有default大小写的情况下对于全局而言,这是一个意外的值。就应用程序而言,您突然具有不确定的行为。

另一方面,使用共享数据区域可能会包含一组在整个应用程序中引用的全局参数。这种方法通常用于内存占用较小的嵌入式应用程序。

在这类应用程序中使用全局变量时,通常将写入数据区域的责任分配给单个组件,而所有其他组件则将该区域视为该区域const并从中读取,而不写入。采用这种方法限制了可能出现的问题。

来自全局变量的一些问题需要解决

修改诸如struct之类的全局变量的源时,必须重新编译使用该变量的所有内容,以便使用该变量的所有内容都知道其真实大小和内存模板。

如果一个以上的组件可以修改全局变量,那么全局变量中的数据不一致会导致问题。对于多线程应用程序,您可能需要添加某种锁定或关键区域来提供一种方法,以便一次仅一个线程可以修改全局变量,而当一个线程在修改变量时,所有更改都已完成。并且在其他线程可以查询或修改变量之前提交。

调试使用全局变量的多线程应用程序可能会更加困难。您可能会遇到竞争状况,这些竞争状况可能会造成难以复制的缺陷。由于几个组件通过全局变量进行通信,尤其是在多线程应用程序中,因此很难理解哪个组件在何时以及如何更改变量。

使用全局变量可能会导致名称冲突。与全局变量同名的局部变量可以隐藏全局变量。使用C编程语言时,还会遇到命名约定问题。解决方法是将系统分为子系统,该子系统具有特定子系统的全局变量,所有全局变量均以相同的前三个字母开头(有关在目标C中解决名称空间冲突的信息,请参阅此内容)。C ++提供了名称空间,使用C语言,您可以通过创建全局可见的结构来解决此问题,该结构的成员是各种数据项以及指向文件中以静态方式提供的数据和函数的指针,因此仅具有文件可见性,因此只能通过以下方式引用它们:全局可见的结构。

在某些情况下,原始应用程序的意图已更改,因此提供单个线程状态的全局变量被修改为允许多个重复线程运行。一个示例是为单个用户设计的简单应用程序,该应用程序使用全局变量来表示状态,然后管理部门发出了添加REST接口以允许远程应用程序充当虚拟用户的请求。因此,现在您不得不复制全局变量及其状态信息,以使单个用户以及远程应用程序中的每个虚拟用户都有自己独特的全局变量集。

使用C ++ namespacestructC技术

对于C ++编程语言,该namespace指令对减少名称冲突的可能性有很大的帮助。namespace以及class各种访问关键字(privateprotectedpublic)提供了封装变量所需的大多数工具。但是,C编程语言不提供此指令。此stackoverflow发布,C中的命名空间,为C提供了一些技术。

一种有用的技术是将单个内存驻留数据区定义为struct具有全局可见性的,并且在其中struct是指向要公开的各种全局变量和函数的指针。全局变量的实际定义使用static关键字指定了文件范围。如果然后使用const关键字指示哪些是只读的,则编译器可以帮助您强制执行只读访问。

使用该struct技术还可以封装全局变量,以使其成为一种恰好是全局变量的包或组件。通过具有此类组件,可以更轻松地管理影响全局的更改以及使用全局的功能。

然而,尽管namespacestruct技术可以帮助解决名称冲突,但是组件间耦合的潜在问题仍然存在,使用全局变量尤其是在现代多线程应用程序中引入了这些问题。


这是最好的解释,说明了其中的所有内容。荣誉!
johndoevodka

您的语言应具有一条代码规则,以防止您使用过多的类耦合。
墨尔本开发商

20

全局变量与您使它们一样糟糕,不少。

如果要创建完全封装的程序,则可以使用全局变量。使用全局变量是一种“罪过”,但是编程上的过失在哲学上是很少的。

如果您查看L.in.oleum,将会看到一种语言,其变量仅是全局的。这是不可扩展的,因为库除了使用全局变量外别无选择。

就是说,如果您有选择并且可以忽略程序员的哲学,那么全局变量并不是那么糟糕。

如果正确使用Gotos,也不是。

最大的“坏”问题是,如果错误使用它们,人们将尖叫,火星着陆器坠毁,世界将爆炸……或类似的东西。


16
对一个迷茫的学生淡化使用全局变量的问题并不是一个好主意。
GEOCHET

3
设计哲学不是客观的。至少不是。仅仅因为大多数程序员不喜欢某种东西,并不意味着就永远不要研究那种东西。在世界没有终结的情况下,可以很容易地普遍使用全局变量。让他去做,奋斗(知道他会),然后学习如何做。
user54650

7
有钱是对的。这个答案不说什么是什么/是不坏(或全局如何可以安全使用),只说:“他们不是那么糟糕,因为一切因此,它只能淡化的问题。
jalf

4
我不同意全局变量只是“随着它们的变坏”。我认为主要的问题之一,尤其是在我们这个大多数人都生活,工作和编程的多开发人员,相互联系的世界中,是全局变量为其他人提供了使您的代码变坏的机会。
gariepy '16

@gariepy直到知道我虽然在谈论关于静态的问题:D好的,那样就是...而且我的应用程序只有一个或两个全局变量,那是Visual Studio,DEBUG和TRACE附带的,我们通常不使用:D
deadManN

19

是的,但是直到停止使用全局变量的代码并开始编写其他使用全局变量的代码之前,您才需要承担全局变量的开销。但是成本仍然存在。

换句话说,这是长期的间接成本,因此大多数人认为这还不错。


19

如果您的代码有可能最终在最高法院的审判中受到严格审查,那么您要确保避免使用全局变量。

请参阅本文: Buggy呼吸检测器代码反映了源代码审查的重要性

两项研究均确定了代码样式方面的一些问题。与审稿人有关的风格问题之一是广泛使用不受保护的全局变量。这被认为是较差的形式,因为它增加了程序状态变得不一致或值被无意修改或覆盖的风险。研究人员还对以下事实表示担忧:整个代码中十进制精度不能始终保持不变。

伙计们,我敢打赌那些开发人员希望他们没有使用全局变量!


6
那是我一段时间以来最好的笑声。为什么为盈利而进行闭源开发是不好的一个真实例子,而全球vars出错的一个很好的例子!
Evil Spork

此处确定的是,对全局变量持轻视态度。这里没有任何内容表明全局变量是代码中的真正问题。SysTest表示,虽然代码“不是以与通常的软件设计最佳实践一致的方式编写的”,但仍将“可靠地产生一致的测试结果”。因此,实际上没有记录到来自全球人员的伤害。正如我所看到的,他们只是确定:“好吧,这些开发人员没有像其他主流国家那样实践相同的编码宗教。”
LionKimbro

17

我会用另一个问题回答这个问题:您是否使用singeltons / singeltons是否有害?

因为(几乎所有)singelton用法是一个荣耀的全局变量。


11
我正要发表一个聪明的评论,说:“只有将它们称为全局变量而不是单例变量,它们才是坏的”,但您击败了我。
smo

我仍在尝试弄清楚什么是单身汉。
GeoffreyF67,2009年

1
@Geoffrey:这里有一些很好SO描述- stackoverflow.com/questions/11831/...和一些好的链接:stackoverflow.com/questions/11831/...
加文·米勒

10
根据记录,单例是一个全局变量,其名称带有美化的Design Patterns(tm)(lol)名称,以使其听起来合法。由于所有相同的原因,这同样很糟糕。
R .. GitHub停止帮助ICE,2010年

@GavinMiller说如果您使用simpleton ...哎呀,单身委婉语是可以的吗?
Juan Mendes

14

问题在于他们的坏处少,而危险的处境则更多。他们有自己的优缺点,在某些情况下,它们是完成特定任务的最有效方法或唯一方法。但是,即使您采取措施始终正确使用它们,它们也容易被滥用。

一些优点:

  • 可以从任何功能访问。
  • 可以从多个线程访问。
  • 在程序结束之前,将永远不会超出范围。

一些缺点:

  • 可以从任何功能访问,而无需显式地作为参数拖入和/或记录下来。
  • 不是线程安全的。
  • 除非采取措施防止全局命名空间污染,否则可能导致名称冲突。

请注意,如果您愿意的话,我列出的前两个优点和前两个缺点完全相同,只是措辞不同。这是因为全局变量的功能确实可以使用,但是使它们有用的功能是所有问题的根源。

一些问题的一些潜在解决方案:

  • 考虑一下它们实际上是解决该问题的最佳还是最有效的解决方案。如果有任何更好的解决方案,使用来代替。
  • 将它们放在具有唯一名称的名称空间[C ++]或单例结构[C,C ++]中(一个很好的例子是Globalsor GlobalVars),或者对全局变量使用标准化的命名约定(例如global_[name]or g_module_varNameStyle(如注释中underscore_d所述) ))。这将记录它们的使用(您可以通过搜索名称空间/结构名称来找到使用全局变量的代码),并最小化对全局名称空间的影响。
  • 对于访问全局变量的任何函数,请明确记录其读取和写入的变量。这将使故障排除更加容易。
  • 将它们放在自己的源文件中,并extern在关联的标头中声明它们,因此可以将它们的使用限制为需要访问它们的编译单元。如果您的代码依赖于很多全局变量,但是每个编译单元只需要访问其中的少数几个变量,则可以考虑将它们排序到多个源文件中,因此将每个文件对全局变量的访问限制为更容易。
  • 设置一种机制来锁定和解锁它们,和/或设计代码,以便实际上需要修改全局变量的函数尽可能少。读取它们比编写它们安全得多,尽管线程争用可能仍会在多线程程序中引起问题。
  • 基本上,最小化对它们的访问,并最大化名称的唯一性。您要避免名称冲突,并尽可能减少可能修改任何给定变量的函数。

它们的好坏取决于您如何使用它们。大多数人倾向于不良地使用它们,因此对它们普遍持谨慎态度。如果使用得当,它们可能是一大福音。但是,如果使用不当,它们会并且再次咬你,何时何地以及如何让你最不期望。

观察它们的好方法是它们本身并不坏,但它们可以启用不良设计,并且可以使不良设计的影响成倍增加。


即使您不打算使用它们,也最好知道如何安全地使用它们并选择不使用它们,而不是不使用它们,因为您不知道如何安全地使用它们。如果您发现自己需要维护依赖于全局变量的现有代码,那么如果您不知道如何正确使用它们,可能会遇到困难。


1
实用主义+1。单例通常只是添加样板来使实例和重构成为成员,最后您得到...全局变量,只是伪装成其他名称。除了单纯地避免技术问题,为什么还要打扰?命名空间很好地作为障碍,但是我发现一个简单g_module_varNameStyle易懂的名称。需要明确的是,我没有使用全局变量,如果我可以很容易地避免它-关键字容易,因为自从我不再相信他们必须避免-或者说模糊 -不惜一切代价,我有一个更好的时间,和我的代码是(震惊!)更整洁了
underscore_d

@underscore_d主要是为了更容易地区分全局变量和局部变量,并在搜索代码时使定位全局变量更容易,目的是防止混淆变量是全局变量还是局部变量/参数/成员/等。只要您保持一致,像您这样的标准命名约定也可以正常工作。使用标准命名约定的想法编辑我的答案,谢谢。
贾斯汀时间-恢复莫妮卡

1
“对于任何函数...明确记录哪些变量”-请记住,这是一个传递关系。如果函数A调用了函数B和C,则它将读取和写入两者(以及直接在其体内写入的变量)的内容
Caleth,

11

正如某人在另一线程中所说(我在措辞中所说)“在您完全理解这样做的后果之前,不应破坏这样的规则”。

有时,全局变量是必需的,或者至少非常有用(例如,使用系统定义的回调)。另一方面,由于您被告知的所有原因,它们也非常危险。

编程的许多方面可能应该留给专家。有时您需要一把非常锋利的刀。但是直到准备就绪,您才可以使用它。


1
我同意,如果您了解后果,可以打破规则,但如果经常发现自己做错了,那说明您做错了
Juan Mendes

9

全局变量通常是不好的,特别是如果其他人正在使用相同的代码并且不想花20分钟的时间来搜索变量所引用的所有位置时。并且添加修改变量的线程带来了一个全新的难题。

在单个翻译单元中使用的匿名命名空间中的全局常量在专业应用程序和库中很好并且无处不在。但是,如果数据是可变的,并且/或者必须在多个TU之间共享,那么您可能希望封装它-如果不是出于设计的目的,那么为了所有人进行调试或使用代码。


9

使用全局变量有点像扫地毯。这是一个快速修复,并且在短期内比使用簸a或真空吸尘器清理起来容易得多。但是,如果您以后再搬地毯,那下面就会大吃一惊。


没有上下文的懒惰隐喻!=答案
underscore_d

1
@underscore_d:我不同意。这是一个讨论性问题,即使未加标签(可能是由于其年代久远),所以这样的回答是完全有效的,并且确实可以解决OP的问题。
gariepy

7

如果全局变量允许您操纵只能在本地修改的程序方面,则它们是不好的。在OOP中,全局变量经常与封装思想冲突。


7

我认为您的教授正在设法养成一个坏习惯,直到它开始。

全局变量有其位置,就像许多人所说的那样,知道何时何地使用它们可能很复杂。因此,我认为,与其深入探讨为什么您的教授决定禁止使用全局变量的原因,方式,时间和地点,不如说是棘手的。谁知道,他将来可能会取消禁令。


7

绝对不。虽然滥用它们...这很糟糕。

为了这个目的而无意识地删除它们只是……没脑子。除非您知道优点和缺点,否则最好按照您的教taught /学到的方法去做明确的事情,但是全局变量没有任何隐含的错误。当您了解利弊时,请更好地做出自己的决定。


3
-1有许多理由要警告全局变量:对我而言,最大的原因是隐藏的依赖关系和全局变量以任何可预测的方式使测试代码极为困难。除非您不重视以自动化方式测试代码的能力,否则我建议全局变量只会给您带来痛苦。此外,在结构良好的程序中,总会有其他选择。
jkp 2012年

1
您的意思是过度概括,仔细使用全局状态不会阻止自动化测试-实际上,几乎所有应用程序都具有全局状态,无论是封装为动态分配的封装好的对象实例还是完全暴露于其中的静态数据从概念上讲没有什么区别,仍然存在依赖关系-只是关于如何编码。
jheriko 2012年

1
究竟。基本上,它们不是很“坏”,而是“容易破坏”。如果您知道如何使用它们而不破坏任何内容,以及何时使用它们而不是替代方法,它们会有所帮助。否则...没有那么多。
贾斯汀时间-恢复莫妮卡

4

全局变量在小型程序中很好,但如果在大型程序中以相同的方式使用,则太可怕了。

这意味着您可以在学习时轻松养成使用它们的习惯。这就是您的教授试图保护您免受伤害的方法。

当您更有经验时,如果可以,将更容易学习。


4

不,它们一点也不差。您需要查看由编译器生成的(机器)代码才能确定,有时使用局部而不是全局要差得多。还要注意,将“静态”放在局部变量上基本上是使其成为全局变量(并创建了真正的全局变量可以解决的其他难看问题)。“本地人”尤其糟糕。

全局变量还使您可以完全控制内存的使用,这与本地变量相比要困难得多。如今,仅在内存非常有限的嵌入式环境中才有意义。在假定嵌入式与其他环境相同并假定整个编程规则都相同之前,需要了解一些知识。

质疑所教的规则是件好事,大多数不是出于被告知的原因。最重要的教训虽然不是这是永远陪伴您的规则,但这是为了通过本课程并继续前进而必须遵守的规则。在生活中,您会发现,对于XYZ公司,您最终将不得不遵循其他编程规则,以保持薪水。在这两种情况下,您都可以争论规则,但我认为您的工作运气要比在学校好得多。教授们,您只是众多学生中的另一个,您的席位很快就会被替换,在您的工作中,您是一小队的成员,他们必须看完这种产品,并且在这种环境下,制定的规则适用于团队成员以及产品和公司的利益,因此,如果每个人都怀有想法,或者对于特定产品,有充分的工程学理由违反了您在大学或一本通用编程书籍中学到的知识,则将您的想法卖给团队,并将其写下来,作为一种有效的方法(如果不是首选的方法) 。在现实世界中,一切都是公平的游戏。

如果您遵守学校或书籍中教给您的所有编程规则,您的编程生涯将非常有限。您可能可以生存并取得丰硕的事业,但是可供使用的环境的广度和宽度将极为有限。如果您知道规则的存在方式和原因,并且可以为之辩护,那就太好了,如果您的唯一理由是“因为我的老师这么说”,那不是那么好。

请注意,像这样的主题经常在工作场所争论不休,并且随着编译器和处理器(和语言)的发展,这样的规则也会不断发展,而不会捍卫您的立场,并且可能会被其他持不同意见的人上课前进。

同时,只要说出最大声或携带最大摇杆的声音就做(直到您叫出最大声并携带最大摇杆的声音为止)。


4
这只是“没有人因收购IBM被解雇”的另一种说法吗?
Gordon Potter,

1
好的一点是,对于某些使用全局变量的应用程序,实际上可以使工作更轻松。通常,使用全局变量是问题的根源,而这些隐式的源之间存在耦合的途径。然而,具有被称为全局的共享存储器区域被用于诸如设备接口之类的许多实现,或者也许包含各种常数的全局参数表或跳转表。
理查德·钱伯斯

4

我想反对整个线程中提出的观点,即它使多线程本身变得更难或更不可能。全局变量是共享状态,但是全局变量的替代方法(例如,传递指针)也可能共享状态。多线程的问题在于如何正确使用共享状态,而不是该状态是否通过全局变量或其他方式共享。

大多数时候,当您执行多线程时,您需要共享一些东西。例如,在生产者-消费者模式中,您可能共享一些包含工作单元的线程安全队列。并且您可以共享它,因为该数据结构是线程安全的。当涉及线程安全时,该队列是否全局是完全无关紧要的。

如果不使用全局变量,那么在整个线程中表达的将程序从单线程转换为多线程的隐含希望将变得更加容易。是的,全局球可以使自己用脚射击更容易,但是有很多方法可以射击自己。

我并不提倡全局变量,就其他观点而言,我的观点仅是程序中的线程数与变量作用域无关。


3

是的,因为如果让不称职的程序员使用它们(尤其是阅读90%的科学家),最终将有600多个全局变量分布在20多个文件中,并且有12,000行的项目,其中80%的函数无效,返回无效值并进行操作完全处于全球状态。

除非您了解整个项目,否则很快就无法理解任一时刻的情况。


2

全局变量的使用实际上取决于要求。它的优点是,它减少了重复传递值的开销。

但是您的教授是对的,因为它引起了安全性问题,因此应尽可能避免使用全局变量。全局变量还会产生有时 难以调试的问题

例如:-

运行时修改变量值的情况。那时,很难确定代码的哪一部分正在修改它以及在什么条件下进行修改。


2

配置而言,全局是好的。当我们希望我们的配置/修改全球影响整个项目

因此,我们可以更改一种配置,并且更改直接针对整个项目。但是我必须警告您,使用全局变量必须非常聪明。


1

迟早,您将需要更改该变量的设置方式或访问该变量时会发生的情况,或者您只需要查找更改的位置。

实际上,最好不要使用全局变量。只需编写dam get和set方法,然后在一天,一周或一个月后需要它们时对它们进行密封。


1

我通常将全局变量用于很少更改的值,例如单例或指向动态加载库中函数的函数指针。在多线程应用程序中使用可变全局变量往往会导致难以跟踪错误,因此,我通常尝试避免这种情况。

使用全局而不是传递参数通常会更快,但是如果您正在编写如今经常使用的多线程应用程序,则通常效果不佳(您可以使用线程静态函数,但是性能提升值得怀疑) 。


1

在Web应用程序中,出于优化的原因,企业可以将会话/窗口/线程/用户特定的数据保存在服务器上,并在连接不稳定的情况下避免丢失工作。如上所述,需要处理比赛条件。我们使用一个类的单个实例来获取此信息,并且对其进行了仔细的管理。


1

归根结底,您的程序或应用仍然可以运行,但是要保持整洁并完全了解发生的事情。如果您在所有函数之间共享一个变量值,则可能很难跟踪哪个函数正在更改该值(如果函数这样做了),并且使调试工作难度增加了一百万倍


0

安全性较小意味着如果将变量声明为全局变量,则任何人都可以操作变量,为此,请以本示例为例,如果您在银行程序中将余额作为全局变量,则用户功能可以操作该变量,银行职员也可以操作这样就产生了一个问题。应该给唯一的用户只读和提取功能,但是当用户亲自在办公桌上提供现金时,银行的业务员可以增加金额。这就是它的工作方式。


-1

在多线程应用程序中,请使用局部变量代替全局变量,以避免出现竞争状况。

当多个线程访问共享资源,并且至少一个线程具有对数据的写访问权时,就会发生竞争状态。然后,程序的结果是不可预测的,并且取决于不同线程对数据的访问顺序。

有关更多信息,请参见https://software.intel.com/zh-cn/articles/use-intel-parallel-inspector-to-find-race-conditions-in-openmp-based-multithreaded-code


对于后代:这在一定程度上是正确的。此答案中的“局部变量”是指线程局部变量,而不是OP所引用的更常见的作用域局部变量。以线程不安全的方式修改全局变量的副作用与以非并行方式更改全局状态的副作用非常不同。
Jules
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.