有没有一种方法可以在Swift中声明一个内联函数?

hgqdbh6s  于 2023-05-05  发布在  Swift
关注(0)|答案(4)|浏览(192)

我是Swift语言的新手。
我想像在C++中一样声明一个 inline 函数,所以我的func声明看起来像这样:

func MyFunction(param: Int) -> Int {
    ...
}

我想这样做

inline func MyFunction(param: Int) -> Int {
    ...
}

我试着在网上搜索,但我没有找到任何相关的东西,也许没有inline关键字,但也许有另一种方法在Swift中内联函数。

xpcnnkqh

xpcnnkqh1#

Swift 1.2将包含@inline属性,其中never__always作为参数。更多信息,请看这里。
如前所述,你很少需要显式地将函数声明为@inline(__always),因为Swift在何时内联函数方面相当聪明。但是,在某些代码中,不内联函数可能是必要的。
Swift-5添加了@inlinable属性,这有助于确保库/框架的内容对于那些链接到您的库的内容是可内联的。请确保您阅读了有关它,因为可能有几个陷阱,可能使它无法使用。它也只适用于声明为public的函数/方法,因为它适用于希望公开内联内容的库。

hof1towb

hof1towb2#

所有功劳都归功于answer,只是总结了链接中的信息。
要使函数内联,只需在函数前添加@inline(__always)

@inline(__always) func myFunction() {

}

然而,值得考虑和学习不同的可能性。有三种可能的内联方式:

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

9bfwbjaz

9bfwbjaz3#

我遇到了一个问题,我需要使用Swift 4.2中引入的@inlinable@usableFromInline属性,所以我想与你分享我的经验。
让我直接讨论这个问题,我们的代码库有一个Analytics Facade模块,可以链接其他模块。
应用目标-〉分析外观模块-〉报告模块X。
Analytics Facade模块有一个名为report(_ rawReport: EventSerializable)的函数,该函数触发报告调用。该函数使用来自报告模块X的示例来发送该特定报告模块X的报告调用。
问题是,一旦用户启动应用程序,就多次调用report(_ rawReport: EventSerializable)函数来发送报告调用,这会产生不可避免的开销,导致我们出现大量崩溃。
此外,如果您在调试模式下将Optimisation level设置为None,那么再现这些崩溃并不是一件容易的事情。在我的情况下,我只能复制它时,我设置的Optimisation levelFastest, Smalles t甚至更高。
解决方案是使用@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)
}

More Info - Cross-module inlining and specialization

p1iqtdky

p1iqtdky4#

我来这里是因为我正在寻找一种方法来混淆代码的安全原因。
内联敏感方法会使从编译的二进制文件中获取敏感信息变得更加困难。
我在这篇文章中找到了一个很好的主题总结:The forbidden inline attribute in swift
作者建议一般不要使用@inline,因为这个决定应该留给编译器来做,而且它甚至没有官方支持。
然而,它也列出了一些@inline可能有益的边缘情况,例如优化速度或代码混淆。

相关问题