属性@inline(__always)
强制编译器内联特定函数。外部库提供的代码如何内联到一个人的项目中?编译器是否实际上从库的可执行文件中复制代码段?
最佳答案
据我所知,@inline(__always)
表示该函数(或类似函数)始终内联,无论如何。这意味着其符号在已编译的模块中公开,因此可以由使用该模块的项目内联它们。因此,“总是”。
这在很大程度上是未记录的属性,我可以在某些stdlib开发人员的internal documentation中找到唯一的官方参考,甚至没有直接描述其行为。我能找到的最好的非官方文档是Vandad Nahavandipoor's disassembly-confirmed investigation into its behavior,它不会尝试确认您所关注的跨模块用例。
在Swift 4.2 中, @inlinable
和 @usableFromInline
分别是introduced来完成此故事。
我的理解:
@inline(__always)
强制每次(无论在何处声明或使用)内联函数(et al)@inlinable
允许将模块中的函数(等)内联到该模块中的调用代码中,或者如果编译器认为必要,则内联到使用该模块的代码中@usableFromInline
允许将模块内部的函数(等)内联到该模块中的@inlinable
调用代码中(如果编译器认为必要的话)。与@inlinable
不同,它们必须是internal
;他们不能是public
根据Swift.org:
不可磨灭的
将此属性应用于函数,方法,计算属性,下标,便捷初始化程序或反初始化程序声明,以将该声明的实现公开为模块 public 接口的一部分。允许编译器在调用站点用符号实现的副本替换对可插入符号的调用。
可插入代码可以与在任何模块中声明的
public
符号进行交互,并且可以与在同一模块中声明的带有usableFromInline
属性的内部符号进行交互。不可插入的代码不能与private
或fileprivate
符号进行交互。此属性不能应用于嵌套在函数内部的声明或
fileprivate
或private
声明。即使无法用此属性标记,在可嵌入函数内部定义的函数和闭包也是隐式可嵌入的。usableFromInline
将此属性应用于函数,方法,计算属性,下标,初始化程序或反初始化程序声明,以允许将该符号用于与声明在同一模块中定义的可插入代码中。该声明必须具有内部访问级别修饰符。标记为
usableFromInline
的结构或类对其属性只能使用public或usableFromInline
的类型。标记为usableFromInline
的枚举只能将 public 或usableFromInline
的类型用于其案例的原始值和关联值。与
public
访问级别修饰符一样,此属性将声明公开为模块 public 接口的一部分。与public
不同,编译器不允许在模块外部的代码中按名称引用标有usableFromInline
的声明,即使声明的符号已导出。但是,模块外部的代码可能仍可以通过使用运行时行为与声明的符号进行交互。标有
inlinable
属性的声明可从inlinable
代码隐式使用。尽管inlinable
或usableFromInline
都可以应用于internal
声明,但同时应用这两个属性都是错误的。