在C/ c++中,全局变量像我的教授认为的那样糟糕吗?


当前回答

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

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

例如:-

变量值在运行时被修改的情况。此时,很难确定是哪部分代码在什么条件下修改了它。

其他回答

全局变量是不好的,如果它们允许您操作应该只在本地修改的程序的某些方面。在面向对象编程中,全局变量经常与封装思想相冲突。

The problem that global variables create for the programmer is that it expands the inter-component coupling surface between the various components that are using the global variables. What this means is that as the number of components using a global variable increases, the complexity of the interactions can also increase. This increased coupling usually makes defects easier to inject into the system when making changes and also makes defects harder to diagnose and correct. This increase coupling can also reduce the number of available options when making changes and it can increase the effort required for changes as often one must trace through the various modules that are also using the global variable in order to determine the consequences of changes.

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

For example if you have a simple global integer variable that is being used as an enumerated indicator that various components use as a state machine and you then make a change by adding a new state for a new component, you must then trace through all the other components to ensure that the change will not affect them. An example of a possible problem would be if a switch statement to test the value of the enumeration global variable with case statements for each of the current values is being used in various places and it so happens that some of the switch statements do not have a default case to handle an unexpected value for the global all of a sudden you have undefined behavior so far as the application is concerned.

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

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

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

当一个全局变量(比如struct)的源代码被修改时,使用它的所有内容都必须重新编译,以便使用该变量的所有内容都知道它的真实大小和内存模板。

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

调试使用全局变量的多线程应用程序可能会更加困难。您可能会遇到竞争条件,从而产生难以复制的缺陷。当多个组件通过一个全局变量进行通信时,特别是在多线程应用程序中,要知道哪个组件在何时以及如何更改变量是非常难以理解的。

Name clash can be a problem with using of global variables. A local variable that has the same name as a global variable can hide the global variable. You also run into the naming convention issue when using the C programming language. A work around is to divide the system up into sub-systems with the global variables for a particular sub-system all beginning with the same first three letters (see this on resolving name space collisions in objective C). C++ provides namespaces and with C you can work around this by creating a globally visible struct whose members are various data items and pointers to data and functions which are provided in a file as static hence with file visibility only so that they can only be referenced through the globally visible struct.

In some cases the original application intent is changed so that global variables that provided the state for a single thread is modified to allow several duplicate threads to run. An example would be a simple application designed for a single user using global variables for state and then a request comes down from management to add a REST interface to allow remote applications to act as virtual users. So now you run into having to duplicate the global variables and their state information so that the single user as well as each of the virtual users from remote applications have their own, unique set of global variables.

使用c++命名空间和C的结构体技术

对于c++编程语言,命名空间指令在减少名称冲突的可能性方面有很大的帮助。命名空间、类和各种访问关键字(私有、受保护和公共)提供了封装变量所需的大部分工具。然而,C编程语言并没有提供这个指令。这篇stackoverflow文章,C中的命名空间,提供了一些C语言的技术。

一种有用的技术是将单个内存常驻数据区域定义为具有全局可见性的结构体,该结构体中包含指向正在公开的各种全局变量和函数的指针。全局变量的实际定义是使用static关键字指定文件范围的。如果你使用const关键字来指示哪些是只读的,编译器可以帮助你强制执行只读访问。

使用struct技术还可以封装全局变量,使其成为一种恰巧是全局变量的包或组件。通过使用这种组件,可以更容易地管理影响全局和使用全局功能的更改。

然而,尽管命名空间或结构技术可以帮助管理名称冲突,但使用全局变量(尤其是在现代多线程应用程序中)所带来的组件间耦合的潜在问题仍然存在。

全局变量有多糟糕就有多糟糕。

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

如果你看看洛杉矶。你会看到一种语言,它的变量是全局的。它是不可伸缩的,因为所有的库都只能使用全局变量。

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

Gotos也是,如果你使用得当的话。

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

我的教授曾经说过这样的话:使用全局变量是可以的,如果你使用正确的话。我不认为我能正确地使用它们,所以我很少使用它们。

是的,因为如果你让不称职的程序员使用它们(阅读90%,尤其是科学家),你最终会得到600多个全局变量分布在20多个文件和一个12000行的项目中,其中80%的函数采用void,返回void,完全在全局状态下运行。

除非你了解整个项目,否则你很快就不可能在任何一个点上理解正在发生什么。