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

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

this学习:默认情况下,假定在块外部声明的非常量变量是外部变量。但是,假定在块外部声明的 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 链接变量。它还定义了它。这就是问题所在,因为您在三个不同的翻译单元中执行此操作:您是在对链接器说您 不小心 命名了三个不同的全局变量,类型相同,相同。


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

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

static S& tool = tool_instance();

function-accessing-a-local-static 以 Scott Meyers 的名字命名为 Meyers 单例。

在 C++17 及更高版本中,您也可以只声明一个 inline 变量。


注意全局变量被认为是Evil™. Quoting Wikipedia on that issue:

The use of global variables makes software harder to read and understand. Since any code anywhere in the program can change the value of the variable at any time, understanding the use of the variable may entail understanding a large portion of the program. Global variables make separating code into reusable libraries more difficult. They can lead to problems of naming because a global variable defined in one file may conflict with the same name used for a global variable in another file (thus causing linking to fail). A local variable of the same name can shield the global variable from access, again leading to harder-to-understand code. The setting of a global variable can create side effects that are hard to locate and predict. The use of global variables makes it more difficult to isolate units of code for purposes of unit testing; thus they can directly contribute to lowering the quality of the code.

免责声明:代码未经编译器处理。

By default, non-const variables declared outside of a block are assumed to be external. However, const variables declared outside of a block are assumed to be internal.

您的情况仍然正确。

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

S tool; // define tool, external scope

但是,在您的 cpp 文件中,extern 关键字仅表示 S 在其他地方定义。

extern S tool; // declare tool

声明定义之间存在差异。 extern in i; 是一个声明:它表示有一个名为 i 的变量,其类型为 int,并暗示它将在其他地方定义。另一方面,int i; 是变量 i 的定义。当您编写定义时,它会告诉编译器创建该变量。如果您在多个源文件中定义了同一个变量,那么您就有了多个定义,编译器(好吧,实际上是链接器)应该会报错。这就是为什么将 definition S tool; 放在 header 中会产生问题:#include 的每个源文件 header 最终都会 defining tool,编译器正确地抱怨。

const 和非 const 定义的区别在于,正如您所说,const int i = 3; 定义了一个名为 i 的变量,即 local 到正在编译的文件。在多个源文件中有相同的定义是没有问题的,因为那些家伙都有内部链接,也就是说,它们在源文件之外是不可见的。当您没有 const 时,例如 int i = 3;,它也定义了一个名为 i 的变量,但它具有 外部链接 ,它,它在源文件之外是可见的,并且在多个文件中具有相同的定义会给你这个错误。 (从技术上讲,导致问题的是同名的定义;两个不同源文件中的int i = 3;double i = 3.0;仍然是重复定义)。