我想我完全理解C ++中inline
关键字的含义。具体来说,它仅意味着两件事:
inline
的函数,ODR规则已放松。因此,您可以在多个TU中定义相同的功能符号,而在链接它们时不会出错。这样就可以在标头中定义函数。call
指令。我可以理解,这两个含义必然在一个方向上相关:2必须隐含1。#2要求函数定义对于调用该函数的所有TU都可用。因此,功能定义必须存在于多个TU中。因此,需要放宽ODR以避免链接器错误。
但是我的问题是另一个方向-为什么将语言设计为1必须隐含2?
在某些情况下和某些设计决策中,希望能够放宽函数的ODR似乎是合理的,而没有则建议编译器实际上应该内联函数代码。如果我有要通过头文件分发的函数,则必须将其标记为inline
以放宽ODR(#1)。但是,即使我对性能有特定的了解,但现在我还是被迫进入第二名。该功能不是内联的理想选择。
我的理解是模板功能不存在这种不必要的含义。将自动放松ODR以使用模板功能(必须如此)。这使我只能将inline
用作性能建议。
我知道在标头文件中分配函数,而不是像静态库,可能不是一个好主意。但是作为一名程序员,我有可能知道自己在做什么,并且我希望这种灵活性。我具有模板功能的灵活性,那么为什么不使用非模板功能呢?
或者是否存在一种便携式的方式来放松ODR而又不建议内联该功能?例如。在MSVC上,您可以执行以下操作:
__declspec(noinline) inline void Foo() {}
此处inline
放宽了ODR,但是__declspec(noinline)
请求编译器 not 实际上内联该调用。但是__declspec(noinline)
不可移植。
谢谢!
答案 0 :(得分:5)
为什么设计该语言时必须将1隐含为2?
语言不是这样设计的。
该语言根本无法明确指定应该或不应该内联扩展的函数-既不是强制性的也不是优选的。
语言都没有指定内联声明暗含对内联扩展的偏好。尽管如此,编译器实现者发现让程序员表达他们对内联扩展的偏好很有用。大概是由于缺乏标准的方式来明确表达该偏好,因此编译器实现者选择让内联声明暗示该偏好。
由于该语言缺乏表达内联扩展偏好的标准方法,因此只能使用特定于实现的语言扩展来表达。
但是
__declspec(noinline)
不可移植。
您可以使用平台检测宏将其移植到具有类似属性的所有实现中。 GCC和Clang有__attribute__((noinline))
。
另一种方法是根本不在乎。编译器仍然可以选择忽略它认为隐含的首选项。如果内联扩展会很昂贵(因为功能很大),那么聪明的编译器应避免扩展它。