既然模板是在头文件中定义的,并且编译器能够确定内联函数是否有优势,那么这有什么意义吗?我听说现代编译器更清楚什么时候内联一个函数,而忽略inline
提示。
编辑:我想接受两个答案,但这是不可能的。为了结束这个问题,我接受Sebastian Mach的答案,因为它获得了大多数选票,他在形式上是正确的,但正如我在评论中提到的那样,我认为Puppy和Component 10的答案也是正确的,从不同的角度来看。
问题出在C++语义上,这在inline
关键字和内联的情况下并不严格。Sebastian Mach说“如果你是认真的,就写内联”,但inline
的实际意思并不清楚,因为它从最初的含义演变成了一个指令,就像Puppy所说的那样,“停止编译器对ODR违规的抱怨”。
发布于 2012-05-10 22:49:32
这不是无关紧要的。不,并不是每个函数模板都是默认的inline
。该标准甚至在显式专门化(temp.expl.spec)中对此进行了显式说明。
具备以下条件:
a.cc
#include "tpl.h"
b.cc
#include "tpl.h"
tpl.h (取自显式专业化认证):
#ifndef TPL_H
#define TPL_H
template<class T> void f(T) {}
template<class T> inline T g(T) {}
template<> inline void f<>(int) {} // OK: inline
template<> int g<>(int) {} // error: not inline
#endif
编译这段代码,看看吧:
g++ a.cc b.cc
/tmp/ccfWLeDX.o: In function `int g<int>(int)':
inlinexx2.cc:(.text+0x0): multiple definition of `int g<int>(int)'
/tmp/ccUa4K20.o:inlinexx.cc:(.text+0x0): first defined here
collect2: ld returned 1 exit status
在执行显式实例化时不声明inline
也可能导致问题。
总结:对于非完全专门化的函数模板,即至少包含一个未知类型的模板,您可以省略inline
,并且不会收到错误,但它们仍然不是inline
。对于完全专门化,即只使用已知类型的专门化,您不能省略它。
提出了的经验法则:如果你是认真的,就编写inline
,只要保持一致即可。它让你更少考虑是否去做,只是因为你能做到。(这条经验法则符合Vandevoorde's/Josuttis's )。
发布于 2012-05-10 22:05:07
这无关紧要。所有的模板都已经是inline
了--更不用说在2012年,inline
关键字的唯一用途就是阻止编译器抱怨ODR违规。您完全正确-您的当前一代编译器将知道自己内联什么,甚至在翻译单元之间也可以做到这一点。
发布于 2012-05-10 22:12:30
正如您所建议的,inline
只是对编译器的一个提示,仅此而已。它可以选择忽略它,或者,实际上,选择内联未标记为内联的函数。
使用带有模板的inline
过去是一种(糟糕的)方法来解决这样的问题,即每个编译单元都会为相同的模板化类创建一个单独的对象,这会在链接时导致重复问题。通过使用inline
(我认为),名称修改的工作原理不同,它绕过了链接时的名称冲突,但代价是代码非常臃肿。3.
马歇尔·克莱恩explains it here比我强。
https://stackoverflow.com/questions/10535667
复制相似问题