正确的全局变量定义/声明

Posted

技术标签:

【中文标题】正确的全局变量定义/声明【英文标题】:Proper Global Variable definition/declaration 【发布时间】:2021-05-29 18:01:12 【问题描述】:

这可能是一个非常直截了当的问题,但由于某种原因,到目前为止我还没有在伟大的互联网上找到答案。

当使用全局变量时,我知道全局变量是不好的,在大多数情况下应该避免使用,但是在极少数情况下全局变量可以最好地完成工作,是否应该同时声明和初始化全局变量?我最近一直在尝试深入研究“尽可能在声明时始终初始化变量”的口头禅,因为这通常会在以后省去很多麻烦,并且在 C++ 中受到鼓励。这条规则是否也适用于全局变量?

如果在声明变量时在其全局范围内初始化变量,这对程序有何影响?这是最佳做法吗?

非常感谢您的建议!

【问题讨论】:

始终初始化全局变量!(或者编译器会使用标准值为您执行此操作) 【参考方案1】:

是的,您确实想初始化全局变量。正如@paladin 评论的那样,如果您不初始化它们,编译器将尝试使用默认值初始化它们。 考虑这个简单的例子:

struct Foo 
    Foo(int x, char *y, double z) 
;

Foo f;

编译器会尝试初始化f,但没有默认构造函数。这会配置一个错误:

<source>:5:5: error: no matching constructor for initialization of 'Foo'
Foo f;
    ^
<source>:1:8: note: candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 0 were provided

所以是的,您需要初始化全局变量,如果您不这样做,编译器会尝试为您完成。

【讨论】:

【参考方案2】:

您希望尽可能在声明变量时对其进行初始化,而不管其范围如何。

对于全局变量,如果在声明它们时不对其进行初始化,则需要在程序开始运行后对其进行初始化,这样就可能在此之前使用全局变量。具有构造函数的类将是默认构造的,这可能会导致在为变量分配适当的值时完成工作并丢弃。

全局变量还有另一个问题:它们的构造/初始化顺序仅由语言部分定义。如果你有两个在不同源模块中声明的全局变量,你不知道会先构造哪个。这可能会导致静态初始化顺序惨败

因此,如果您初始化它们,您可能会遇到问题,或者如果您不初始化它们,则会遇到不同的问题。这是应该避免使用全局变量的原因之一。

解决办法是什么?您可以将全局变量包装到访问器函数中。这将确保变量已正确初始化。因此,而不是简单的声明:

SomeType big = ReadBig();

你可以把它放到一个函数中:

const SomeType &GetBig() 
    static SomeType big = ReadBig();
    return big;

这还有一个好处是你的全局变量const,所以如果有必要,它不能被改变。

【讨论】:

"静态初始化顺序惨败" 不是只有在这些全局变量不相互独立时才会发生吗? (如果这些全局变量不是相互独立的,那么您至少有 1 个全局变量太多了。)我也很确定全局变量也可能是全局常量。我发现您在函数的帮助下重新发明全局变量的方法很好奇。我认为那里没有优势,但有劣势。 @paladin 如果全局变量是独立的,那么它们的构造顺序无关紧要。当顺序很重要时就会出现问题。让函数返回指向局部静态变量的引用或指针的方法很常见。工厂模式的一种实现将做到这一点(类的静态成员函数返回对函数内声明的局部静态变量的引用)。

以上是关于正确的全局变量定义/声明的主要内容,如果未能解决你的问题,请参考以下文章

c语言怎样声明和定义全局变量

Java 全局变量 声明与定义

C 语言能不能在头文件定义全局变量?

C/c++中 数组全局变量的定义声明 与 引用声明

fortran 定义全局变量

C#中在哪里声明全局变量啊,具体位置在哪儿,我是初学者。。。