我知道全局变量是不好的,应该尽量避免。但是,例如在使用 MPI 编写并行程序时,某些变量只会被初始化一次,并且永远不会改变(此任务的数量、任务总数等)。将这些变量作为全局变量仍然被认为是不好的做法吗?由于您几乎总是需要访问这些变量,因此在 main 中为它们创建一个类并将指向它的指针传递给程序中 99% 的函数似乎很愚蠢。到目前为止,我的方法是将它们隐藏在名称空间 mpi_glob 中(对于 C++ 的情况,我想我不会费心将它们放在 C 中的结构中来模拟名称空间)。我想这个问题也适用于其他仅设置一次的变量,例如单位制等。
3 回答
全局变量“不好”的原因是它们引入了难以识别和跟踪的单独源文件之间的耦合。特别是,如果全局变量在程序中的某个时刻出现意外状态,则很难弄清楚它在哪里被修改。
将全局变量替换为通过引用传递给程序中每个函数的局部变量并不能消除该问题。在设计方面,它是“流浪数据”,即即使在不需要的地方也会四处游荡的数据。
现在,这里的重点是,正如您所建议的,初始化一次且从未更改过的数据不会出现使全局变量“坏”的问题。由于问题不存在,因此不需要解决方案。
不应该遵循任何规则,具体情况完全取决于您正在编写的程序类型。
如果您的程序相对较小(或者您是唯一一个编写/维护它的人),那么将“全局”变量留在一个特殊的命名空间中可能没问题。至少这样你就不会在某个地方的本地范围内意外地对它们进行阴影或踩踏。这是假设你没有做这样的事情:
using namespace mpi_glob;
这与仅将全局变量放在某个文件中并且并不能很好地保护它们几乎没有什么不同。
如果它通过使用全局变量使您的程序更加清晰易懂,那么就使用它们。如果可以将它们保留在本地,请将它们保留在本地,因为从长远来看,这通常会使维护变得更简单。
我想Singleton应该可以帮助您更好地管理它,因此您不必传递指针。实际上,mpi_glob
做同样的事情,Singleton
只是更习惯的方式。
或者,您仍然可以使用全局变量——它们本身也不错。如果你想强调一次性赋值,你可以声明它们const
并通过静态初始化器设置它们,如下所示:
const int number_of_tasks = get_preconfigured_number_of_tasks();
如果您的全局变量用于保存编译时常量,那么将它们替换为enum
成员或预处理器定义是非常好的。这样做会减轻编译器的负担,因为它可以在没有内存访问的情况下就地使用立即值。
归功于 Pete Becker 在他的评论中指出 Singleton 问题。如果这些问题也困扰您,那么可以采取完全不同的方法。
还记得 Java 程序是如何实现的吗?有一个带有主方法的主类,所有程序的工作都在该主方法中运行。Main 仍然是成员函数,即它可以独占访问主类的一些私有字段(在 Java 的情况下它们必须是静态的,但这不是这里的重点)。
我们可以进一步将该概念扩展到类似命令的实现。与传统 Java 的不同之处在于您的 main 等效方法不是静态的,而具有特定于包含程序的值的全局变量是非静态成员变量。所有需要访问全局状态数据的函数都将转换为成员函数。这是可能的,因为 main 方法也是成员函数。
这样,我认为,您可以实现更好的封装和数据安全。