“内联”是啥意思?
Posted
技术标签:
【中文标题】“内联”是啥意思?【英文标题】:What does "internal linkage" mean?“内联”是什么意思? 【发布时间】:2014-05-14 04:12:13 【问题描述】:在标准中它说:
当名称具有内部链接时,它表示的实体可以是 由同一翻译单元中其他范围的名称引用。
和:
具有命名空间范围 (3.3.6) 的名称具有内部链接,如果它是 名称 — 一个变量、函数或函数模板,它是 显式声明为静态;
所以考虑下面的代码:
#include <stdio.h>
namespace A
/* a with internal linkage now.
Entity denoted by a will be referenced from another scope.
This will be main() function scope in my case
*/
static int a=5;
int main()
int a; //declaring a for unqualified name lookup rules
printf("%d\n",a);//-1216872448
我真的不明白标准中的定义。这是什么意思:
它表示的实体可以通过其他范围的名称来引用 同一个翻译单元。
【问题讨论】:
【参考方案1】:translation unit 通常由单个源文件和所有#include
d 文件组成,并生成一个目标文件。
命名空间范围中的名称默认具有外部链接,这意味着您可以从其他翻译单元引用该名称(使用范围解析运算符或使用指令)。但如果名称以static
限定,则链接变为internal,并且名称不能在定义它的翻译单元之外引用。
在您的示例中,如果命名空间 A
、名称 a
和 main
方法在 same 翻译单元中,则您可以访问 a
。但是在main
中,您声明了另一个变量a
,它将a
隐藏在命名空间A
中。并且 main 中的 a
未初始化,因此当您打印时,它实际上打印了来自 main
中声明的 a
的垃圾值。如果您想在main
中使用A
中的a
,请使用cout<<A::a
或在包含main
的源文件中使用using namespace A;
。
【讨论】:
那么为什么 a 没有打印在 main 函数中?【参考方案2】:“翻译单元”是编译器一次处理的代码块的技术术语。通常这是一个.cpp
源文件及其包含的所有头文件。
实际上,这通常意味着翻译单元被编译成目标文件。这个目标文件不是完整的程序;它必须与其他目标文件“链接”才能制作最终程序。 “链接”过程只是简单地匹配在一个翻译单元中定义并在一个或多个其他单元中使用的各种功能。
例如,您的翻译单元调用printf
,但printf
的定义(机器代码)实际上在另一个翻译单元中。所以链接器必须知道 1) printf
的实际定义在哪里,以及 2) 在你的代码中它被调用的位置,所以它可以将 1) 的地址插入 2)。
printf
是具有外部链接的事物的示例;它可以链接到其翻译单元外部的事物。另一方面,具有 internal 链接的内容只能在其翻译单元内链接。因此,在您的示例中,main
可以访问A::a
,它在命名空间级别声明为static
,但在此翻译单元外部 定义的函数无法看到A::a
。这是因为编译器从目标文件的链接表中省略了对A::a
的引用。
最后,您的示例中发生的事情是main
看到的a
是它在自身内部声明的那个,它是未初始化的。这就是它打印垃圾值的原因。如果您将main
更改为:
int main()
printf("%d\n", A::a);
它将打印5
。
【讨论】:
【参考方案3】:它表示的实体可以被同一翻译单元中其他范围的名称引用。
要理解这一点,您必须了解实体和名称之间的区别。
在您的主函数中,您正在创建一个新实体并将其命名为a
。该名称不是指名称空间 A 中名为 a
的同一实体。它是不同的实体,不仅因为它具有不同的链接,还因为它位于不同的名称空间中。
默认情况下,局部变量没有链接,因此它们总是指定一个新实体。例如
static int a = 5; // a new entity with name `a` that has internal linkage.
int main()
int a; // This is a new entity local to function main with no linkage.
// It isn't initialized, so you have undefined behavior if you try to
// access it.
在本例中,您有两个实体,均名为 a
,但它们引用不同的实体,因为它们位于不同的作用域中,具有不同的链接。
标准所指的情况是这样的:
static int a = 5; // A new entity with the name `a` that has internal linkage.
void f()
extern int a; // This is a new declaration for the same entity called `a` in
// the global scope.
现在您只有一个实体,但在两个不同的范围内仍然有两个名称。这两个名字指的是同一个实体。
这是一个非常棘手的问题。因为f()
中的声明有extern
,所以您说您希望f 的a
引用在别处定义的实体。但是,由于在全局范围内已经有一个声明为 static
的 a
声明,因此它使 a
具有内部链接而不是外部链接。
请注意,为具有内部链接的同一实体设置两个名称并没有太大的实际价值,因为您始终可以只使用第一个名称。
【讨论】:
以上是关于“内联”是啥意思?的主要内容,如果未能解决你的问题,请参考以下文章
为啥我不能在组件道具中使用内联函数?可以举个例子详细解释一下吗?失去所有状态是啥意思?
将“this”传递给新对象的内联重写方法的正确方法是啥? [复制]