Aren的非const变量默认被认为是外部变量?

时间:2016-12-15 14:11:01

标签: c++ global extern linkage

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;

的工作原理。不是外部违约吗?

3 个答案:

答案 0 :(得分:3)

命名空间范围内的声明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();

函数访问本地静态称为Meyers'单身人士,在斯科特迈尔斯之后。

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

请注意,全局变量被视为Evil™。引用Wikipedia on that issue

  

全局变量的使用使得软件更难以阅读和理解。由于程序中任何地方的任何代码都可以随时更改变量的值,因此理解变量的使用可能需要了解程序的大部分内容。全局变量使得将代码分离成可重用的库变得更加困难。它们可能导致命名问题,因为在一个文件中定义的全局变量可能与用于另一个文件中的全局变量的相同名称冲突(从而导致链接失败)。同名的局部变量可以保护全局变量不被访问,从而再次导致难以理解的代码。全局变量的设置可能会产生难以定位和预测的副作用。全局变量的使用使得为了单元测试而隔离代码单元变得更加困难;因此,它们可以直接导致降低代码质量。

免责声明:编译人员未触及的代码。 功能

答案 1 :(得分:1)

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

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

答案 2 :(得分:0)

  

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

在您的情况下,该陈述仍然是正确的。

Student setCourses(... { .... return this; } 中,MyTools.h是外部的。

tool

但是,在S tool; // define tool, external scope 文件中,cpp关键字仅表示extern在其他位置定义。

S