有没有办法在swift中声明内联函数?

Gib*_*nem 35 inline-functions swift

我对快速的语言很新

我想在c ++中声明一个内联函数,所以我的有趣声明就像

func MyFunction(param: Int) -> Int {
...
...
...
}
Run Code Online (Sandbox Code Playgroud)

我想要做类似的事情

inline func MyFunction(param: Int) -> Int {
...
...
...
}
Run Code Online (Sandbox Code Playgroud)

我试图在网上搜索,但我没有找到任何相关的可能没有内联关键字,但也许还有另一种内联函数的方法

非常感谢 :)

Mad*_*ane 46

Swift 1.2将包含@inline属性,with never__alwaysas参数.有关详细信息,请参阅此处.

如前所述,您很少需要显式声明一个函数,@inline(__always)因为Swift在何时内联函数方面相当聪明.但是,在某些代码中可能不需要内联函数.

  • "但是,在某些代码中,没有内联函数可能是必要的." 你能举一个例子,出于教育目的吗? (3认同)

kga*_*dis 15

所有这些都归功于答案,只是总结了链接中的信息.

要使函数内联只需@inline(__always)在函数前添加:

@inline(__always) func myFunction() {

}
Run Code Online (Sandbox Code Playgroud)

但是,值得考虑和了解不同的可能性.内联有三种可能的方法:

  • 有时 - 确保有时内联函数.这是默认行为,您无需执行任何操作!Swift编译器可能会自动将函数内联为优化.
  • 始终 - 将确保始终内联该功能.通过@inline(__always)在函数之前添加来实现此行为.使用"如果您的功能相当小,您希望您的应用程序运行得更快."
  • 从不 - 确保永远不会内联该功能.这可以通过@inline(never)在函数之前添加来实现.使用"如果您的功能很长,并且您希望避免增加代码段大小."


Sha*_*afa 7

我遇到了一个需要使用的问题@inlinable以及@usableFromInlineSwift 4.2 中引入的属性,因此我想与您分享我的经验。

让我直接讨论这个问题,我们的代码库有一个链接其他模块的 Analytics Facade 模块。

应用程序目标 -> 分析外观模块 -> 报告模块 X.

Analytics Facade 模块有一个称为report(_ rawReport: EventSerializable)触发报告调用的函数,该函数使用报告模块 X 中的实例来发送该特定报告模块 X 的报告调用。

问题是,report(_ rawReport: EventSerializable)一旦用户启动应用程序,多次调用该函数来发送报告调用会产生不可避免的开销,从而导致我们发生大量崩溃。

此外,如果您在调试模式下设置Optimisation level为,那么重现这些崩溃并不是一件容易的事。就我而言,只有当我将 t 设置为t 甚至更高None时,我才能重现它。Optimisation levelFastest, Smalles

解决方案是使用@inlinable@usableFromInline

使用函数体并将其导出为模块接口的一部分,使其在从其他模块引用时可供优化器使用@inlinable@usableFromInline

@usableFromInline属性将内部声明标记为模块二进制接口的一部分,允许从代码中使用它,@inlinable而无需将其公开为模块源接口的一部分。

跨模块边界,运行时泛型引入了不可避免的开销,因为具体化类型元数据必须在函数之间传递,并且必须使用各种间接访问模式来操作泛型类型的值。对于大多数应用程序来说,与代码本身执行的实际工作相比,这种开销可以忽略不计。

针对此框架构建的客户端二进制文件可以调用这些泛型函数,并且在启用优化的情况下构建时,由于消除了抽象开销,因此可以享受可能的性能改进。

示例代码:

@inlinable public func allEqual<T>(_ seq: T) -> Bool
    where T : Sequence, T.Element : Equatable {
        var iter = seq.makeIterator()
        guard let first = iter.next() else { return true }

        func rec(_ iter: inout T.Iterator) -> Bool {
            guard let next = iter.next() else { return true }
            return next == first && rec(&iter)
        }

        return rec(&iter)
}
Run Code Online (Sandbox Code Playgroud)

更多信息 - 跨模块内联和专业化