5

假设我在我的预编译头文件中包含一个头文件,其中包含一堆内联函数,可在项目的任何 TU 中任何需要的地方用作帮助程序——编写这些内联的正确方法是什么?

1)作为静态内联?例如:

static inline BOOL doSomethingWith(Foo *bar)
{
   // ...
}

2)作为外部内联?例如:

在 Shared.h

extern inline BOOL doSomethingWith(Foo *bar);

在 Shared.m

inline BOOL doSomethingWith(Foo *bar)
{
   // ...
}

我对内联的意图是:

  • 通过封装通用指令使代码不那么冗长
  • 集中它们包含的代码以帮助未来的维护
  • 为了类型安全而使用它们而不是宏
  • 能够有返回值

到目前为止,我只在野外看到过变体 1)。我已经读过(遗憾的是再也找不到它了)变体 1)没有准确地将内联函数的主体移动到调用者中,而是创建了一个新函数,这只能extern inline确保这种行为。

4

2 回答 2

7

由于您给出的原因,跳过是否应该内联,在 Cocoa 中内联的标准方法是使用预定义的宏NS_INLINE- 在源文件中使用函数或在导入的标头中使用它。所以你的例子变成:

NS_INLINE BOOL doSomethingWith(Foo *bar)

对于 GCC/Clang,宏使用staticalways_inline属性。

大多数(可能是所有)编译器不会内联extern inline,因为它们一次在单个编译单元上运行 - 一个源文件及其所有包含。

于 2013-09-04T21:16:14.357 回答
5

通过封装通用指令使代码不那么冗长

非内联函数也这样做......

集中它们包含的代码以帮助未来的维护

那么你应该有非inline功能,你不觉得吗?

为了类型安全而使用它们而不是宏

能够有返回值

这些对我来说似乎还可以。


好吧,当我编写inline函数时,我通常会制作它们static——通常就是这样做的。(否则,如果您不够小心,您可能会得到各种神秘的链接器错误。)重要的是要注意它不会inline影响函数的可见性,因此如果您想在多个文件中使用它,则需要修饰符。static

一个extern inline函数没有多大意义。如果你只有一个函数的实现,那就违背了内联的目的。如果您使用链接时优化(其中跨文件内联由链接器完成),那么编译器inline的提示无论如何都不是很有用。

只有 extern inline 可以确保这种行为。

它根本不“确保”任何事情。没有可移植的方法来强制内联 - 事实上,大多数现代编译器完全忽略关键字并使用启发式方法来决定何时内联。在 GNU C 中,您可以使用属性强制内联__attribute__((always_inline)),但除非您有充分的理由,否则您不应该这样做。

于 2013-09-04T20:52:33.417 回答