据我所知,C ++中的变量有三种可能的链接值 - 没有链接,内部链接和外部链接。
因此,外部链接意味着可以在多个文件中访问变量标识符,而内部链接意味着可以在同一文件中访问它。但内部联系的重点是什么?为什么不只有两个可能的标识符链接 - 没有链接和外部链接?对我来说,似乎全局(或文件)范围和内部联系起着同样的作用。
是否存在内部链接实际上有用且未被全局范围覆盖的用例?
在下面的例子中,我有两段代码 - 第一段链接到static int i11(有内部链接),第二段没有。两者都做了同样的事情,因为main已经可以访问变量i11,因为它的文件范围很大。那么为什么要有一个称为内部联系的单独链接。
static int i11 = 10;
int main()
{
extern int i11;
cout << ::i11;
return 0;
}
给出与
相同的结果static int i11 = 10;
int main()
{
cout << ::i11;
return 0;
}
编辑:为了增加更多清晰度,根据下面的HolyBlackCat定义,内部链接实际上意味着您可以在同一个翻译单元中转发声明变量。但是为什么你甚至需要对文件中已经全局访问的变量这样做呢。这个功能有什么用例吗?
答案 0 :(得分:7)
每个例子:
外部联系:
foo.h
extern int foo; // Declaration
foo.cpp
extern int foo = 42; // Definition
bar.cpp
#include "foo.h"
int bar() { return foo; } // Use
内部联系:
foo.cpp
static int foo = 42; // No relation to foo in bar.cpp
bar.cpp
static int foo = -43; // No relation to foo in foo.cpp
没有联系:
foo.cpp
int foo1() { static int foo = 42; foo++; return foo; }
int foo2() { static int foo = -43; foo++; return foo; }
当然,您同意函数foo
和foo1
中的foo2
变量必须具有存储空间。这意味着他们可能必须拥有名称,因为汇编程序和链接器的工作方式。这些名称不能冲突,任何其他代码都不应该访问。 C ++标准编码的方式是“没有联系”。还有一些其他情况也可以使用它,但是对于那些使用存储的情况不太明显的事情。 (例如class
你可以想象vtable有存储空间,但对于typedef
来说,这主要是关于名称访问范围的语言规范细节问题。)
C ++指定了一些最不常见的分母链接模型,可以映射到实际平台上更丰富的实际链接器模型。在实践中,这是非常不完美的,许多真实系统最终使用属性,编译指示或编译器标志来获得对链接类型的更大控制。为了做到这一点并仍然提供一种相当有用的语言,人们会进入名称修改和其他编译器技术。如果C ++曾试图提供更大程度的编译代码互操作,例如Java或.NET虚拟机,那么语言很可能会获得更清晰,更精细的链接控制。
编辑:更清楚地回答这个问题......标准必须定义它如何用于访问源语言中的标识符和编译代码的链接。定义必须足够强大,以便正确编写的代码永远不会对未定义或多重定义的事物产生错误。肯定有比C ++更好的方法来实现这一点,但它主要是一种进化的语言,规范在某种程度上受到编译基板的影响。实际上,三种不同类型的联系是:
在程序集中,它们倾向于映射到全局声明,文件本地声明和具有合成唯一名称的文件本地声明。
对于在程序的不同部分声明具有不同链接的相同名称以及确定extern int foo
从给定位置引用的内容的情况,它也是相关的。
答案 1 :(得分:-1)
外部链接用于当文件彼此独立编译时(#include .h,.c和.cpp文件不是彼此独立编译的)。外部变量的特殊之处在于它可以在单独编译的文件之间使用。