简体   繁体   English

C ++中内部链接的重点是什么?

[英]What is the point of internal linkage in C++

I understand that there are three possible linkage values for a variable in C++ - no linkage, internal linkage and external linkage. 据我所知,C ++中的变量有三种可能的链接值 - 没有链接,内部链接和外部链接。

So external linkage means that the variable identifier is accessible in multiple files, and internal linkage means that it is accessible within the same file. 因此,外部链接意味着可以在多个文件中访问变量标识符,而内部链接意味着可以在同一文件中访问它。 But what is the point of internal linkage? 但内部联系的重点是什么? Why not just have two possible linkages for an identifier - no linkage and external linkage? 为什么不只有两个可能的标识符链接 - 没有链接和外部链接? To me it seems like global (or file) scope and internal linkage serve the same purpose. 对我来说,似乎全局(或文件)范围和内部链接起着同样的作用。

Is there any use case where internal linkage is actually useful that is not covered by global scope? 是否存在内部链接实际上有用且未被全局范围覆盖的用例?

In the below example, I have two pieces of code - the first one links to the static int i11 (which has internal linkage), and the second one does not. 在下面的例子中,我有两段代码 - 第一段链接到static int i11(有内部链接),第二段没有。 Both pretty much do the same thing, since main already has access to the variable i11 due to its file scope. 两者都做了同样的事情,因为main已经可以访问变量i11,因为它的文件范围很大。 So why have a separate linkage called internal linkage. 那么为什么要有一个叫做内部联系的单独链接

static int i11 = 10;

int main()
{
extern int i11;
cout << ::i11;
return 0;
}

gives the same result as 给出了相同的结果

static int i11 = 10;

int main()
{
 cout << ::i11;
 return 0;
}

EDIT: Just to add more clarity, as per HolyBlackCat's definition below, internal linkage really means you can forward-declare a variable within the same translation unit. 编辑:为了增加更多的清晰度,根据HolyBlackCat的定义,内部链接实际上意味着你可以在同一个翻译单元中转发声明一个变量。 But why would you even need to do that for a variable that is already globally accessible within the file .. Is there any use case for this feature? 但是为什么你甚至需要为文件中已经全局访问的变量做到这一点..这个功能有什么用例吗?

Examples of each: 每个例子:

External linkage: 外部联系:

foo.h

    extern int foo; // Declaration

foo.cpp

    extern int foo = 42; // Definition

bar.cpp

    #include "foo.h"

    int bar() { return foo; } // Use

Internal linkage: 内部联系:

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

No linkage: 没有联系:

foo.cpp

    int foo1() { static int foo = 42; foo++; return foo; }
    int foo2() { static int foo = -43; foo++; return foo; }

Surely you will agree that the foo variables in functions foo1 and foo2 have to have storage. 当然你会同意函数foo1foo2中的foo变量必须有存储空间。 This means they probably have to have names because of how assemblers and linkers work. 这意味着他们可能必须拥有名称,因为汇编程序和链接器的工作方式。 Those names cannot conflict and should not be accessible by any other code. 这些名称不能冲突,任何其他代码都不应该访问。 The way the C++ standard encodes this is as "no linkage." C ++标准编码的方式是“没有联系”。 There are a few other cases where it is used as well, but for things where it is a little less obvious what the storage is used for. 还有一些其他情况也可以使用它,但是对于那些使用存储的情况不太明显的事情。 (Eg for class you can imagine the vtable has storage, but for a typedef it is mostly a matter of language specification minutiae about access scope of the name.) (例如,对于class您可以想象vtable具有存储空间,但对于typedef ,主要是关于名称的访问范围的语言规范细节问题。)

C++ specifies somewhat of a least common denominator linkage model that can be mapped onto the richer models of actual linkers on actual platforms. C ++指定了一些最不常见的分母链接模型,可以映射到实际平台上更丰富的实际链接器模型。 In practice this is highly imperfect and lots of real systems end up using attributes, pragmas, or compiler flags to gain greater control of linkage type. 在实践中,这是非常不完美的,许多真实系统最终使用属性,编译指示或编译器标志来获得对链接类型的更大控制。 In order to do this and still provide a reasonably useful language, one gets into name mangling and other compiler techniques. 为了做到这一点并仍然提供一种相当有用的语言,人们会进入名称修改和其他编译器技术。 If C++ were ever to try and provide a greater degree of compiled code interop, such as Java or .NET virtual machines do, it is very likely the language would gain clearer and more elaborate control over linkage. 如果C ++曾试图提供更大程度的编译代码互操作,例如Java或.NET虚拟机,那么语言很可能会获得更清晰,更精细的链接控制。

EDIT: To more clearly answer the question... The standard has to define how this works for both access to identifiers in the source language and linkage of compiled code. 编辑:更清楚地回答这个问题......标准必须定义它如何用于访问源语言中的标识符和编译代码的链接。 The definition must be strong enough so that correctly written code never produces errors for things being undefined or multiply defined. 定义必须足够强大,以便正确编写的代码永远不会对未定义或多重定义的事物产生错误。 There are certainly better ways to do this than C++ uses, but it is largely an evolved language and the specification is somewhat influenced by the substrate it is compiled onto. 肯定有比C ++更好的方法来实现这一点,但它主要是一种进化的语言,规范在某种程度上受到编译基板的影响。 In effect the three different types of linkage are: 实际上,三种不同类型的联系是:

  • External linkage: The entire program agrees on this name and it can be access anywhere there is a declaration visible. 外部链接:整个程序同意此名称,并且可以在有可见声明的任何地方访问。
  • Internal linkage: A single file agrees on this name and it can be accessed in any scope the declaration is visible. 内部链接:单个文件同意此名称,并且可以在声明可见的任何范围内访问它。
  • No linkage: The name is for one scope only and can only be accessed within this scope. 无链接:名称仅适用于一个范围,只能在此范围内访问。

In the assembly, these tend to map into a global declaration, a file local declaration, and a file local declaration with a synthesized unique name. 在程序集中,它们倾向于映射到全局声明,文件本地声明和具有合成唯一名称的文件本地声明。

It is also relevant for cases where the same name is declared with different linkage in different parts of the program and in determining what extern int foo refers to from a given place. 它也适用于在程序的不同部分中使用不同的链接声明相同名称并确定extern int foo从给定位置引用的内容的情况。

External linkage is for when you have files being compiled independently of each other (#included .h, .c, and .cpp files are not compiled independently of each other). 外部链接用于在文件彼此独立编译时(#include .h,.c和.cpp文件不是彼此独立编译的)。 An extern variable is special in that it can be used between files being compiled separately. 外部变量的特殊之处在于它可以在单独编译的文件之间使用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM