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

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

其他回答

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

使用全局变量有点像扫地毯下的灰尘。这是一种快速的解决方法,在短期内比用吸尘盆或吸尘器清理要容易得多。然而,如果你后来搬了地毯,下面会有一个大的惊喜。

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

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

实际上,不使用全局变量总是更好。只需编写大坝获取和设置方法,并在一天、一周或一个月后当你需要它们时通知你。

我想用另一个问题来回答这个问题:你使用singeltons吗/ singeltons不好吗?

因为(几乎所有)单变量的使用都是一个美化的全局变量。