默认情况下,非常量变量不被视为外部变量吗?

Aren't non-const variable considered external by default?

本文关键字:变量 外部 情况下 非常 常量 默认      更新时间:2023-10-16

从此中学习:默认情况下,假定在块之外声明的非const变量是外部的。但是,假定在块之外声明的const变量是内部的。

,但是如果我在MyTools.h中写下此:

#ifndef _TOOLSIPLUG_
#define _TOOLSIPLUG_
typedef struct {
    double LN20;
} S;
S tool;
#endif // !_TOOLSIPLUG_

我包括MyTools.h 3次(来自3个不同的.cpp),它说tool已经定义(在链接器阶段)。只有我更改:

extern S tool;

有效。不外部默认值?

命名空间范围的声明 S tool;确实声明了 extern链接变量。它也定义了它。这就是问题所在,因为您在三个不同的翻译单元中这样做:您是在向链接器说偶然地命名了三个不同的全局变量,相同类型。


实现您似乎想要的效果的一种方法,即标题中声明的一个全局共享变量,就是这样做:

inline auto tool_instance()
    -> S&
{
    static S the_tool;    // One single instance shared in all units.
    return the_tool;
}
static S& tool = tool_instance();

函数访问-A本地静态被称为Meyers'Singleton,在Scott Meyers之后。

在C 17及以后您也可以声明inline变量。


请注意,全球变量被视为邪恶和贸易;引用Wikipedia在该问题上:

” 全局变量的使用使软件更难读取和理解。由于程序中任何地方的任何代码都可以随时更改变量的值,因此了解变量的使用可能需要了解程序的大部分。全局变量使将代码分开为可重复使用的库更加困难。它们可能导致命名问题,因为一个文件中定义的全局变量可能与另一个文件中的全局变量使用的同名相互冲突(从而导致链接失败)。同名的局部变量可以将全局变量屏蔽到访问中,再次导致难以理解的代码。全局变量的设置可以创建难以找到和预测的副作用。全局变量的使用使得为单位测试的目的隔离代码单位变得更加困难。因此,它们可以直接有助于降低代码的质量。

免责声明:编译器的手不触摸代码。

声明 defution 之间存在差异。extern int i;是一个声明:它说有一个名为i的变量,其类型为intextern意味着将其定义在其他地方。另一方面,int i;是变量i的定义。当您编写定义时,它告诉编译器创建该变量。如果您在多个源文件中具有相同变量的定义,则您有多个定义,并且编译器(嗯,实际上,链接器)应该抱怨。这就是为什么将定义 S tool;放在标题中会产生问题:每个源文件#Incc分Include the Header结束定义 tool,并且编译器正确地抱怨。

>

正如您所说,const和非const定义之间的差异是const int i = 3;定义了一个名为i的变量,该变量是 local 的变量。在一个以上的源文件中具有相同的定义没有问题,因为这些人都具有内部链接,也就是说,在源文件之外它们不可见。例如,如果您没有const,则使用int i = 3;,它也定义了一个名为i的变量,但它具有外部链接,它是在源文件外看到的,并且具有相同的多个文件中的定义会给您带来错误。(从技术上讲,它的定义是相同名称导致问题的定义; int i = 3;double i = 3.0;在两个不同的源文件中仍然是重复的定义)。

默认情况下,假定在块之外声明的非const变量是外部的。但是,假定在块之外声明的const变量是内部的。

在您的情况下,该语句仍然是正确的。

在您的MyTools.h中,tool是外部的。

S tool; // define tool, external scope

但是,在您的cpp文件中,extern关键字仅表示S是定义的,否则。

extern S tool; // declare tool