2012-05-10 18 views
82

由于模板是在头文件中定义的,编译器能够确定内联函数是否有利,它有什么意义吗?我听说现代编译器知道何时内联函数并忽略inline提示。在模板中使用内联关键字有意义吗?


编辑:我想接受这两个答案,但这是不可能的。要关闭我接受phresnel这个问题的答案,因为它获得多数选票,他是正式的权利,但正如我在评论中提到,我认为小狗的和组件10的答案是正确之辈,从不同的角度来看。

问题出在C++语义上,在inline关键字和内联的情况下不严格。 phresnel表示“如果你的意思是内联写入”,但inline的实际含义并不清楚,因为它从原来的含义演变为“阻止编译器对ODR违规行为嗤之以鼻”的指令为Puppy说。

回答

65

这并非无关紧要。不,并不是每个功能模板默认为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 C++ Template: The Complete Guide)。

+0

明确的专业化是真的 - 它们就像普通的功能一样。但是在这里 - >'template inline T g(T){}'不需要内联,你可以写'template T g(T){}' – doc

+1

可以写成true。但是这并不意味着内联,即使它看起来像这样。 Vandevoorde和Josuttis在_C++模板中也完全说明了这一点:完整的Guide_ –

+0

模板可以有多个定义(3.2/5) - > http://stackoverflow.com/a/10211420/205955我声明这并不意味着它们是正式内联的。但是,这一切都归结于实践。所以,从不同的角度来看,这两个答案都是正确的。 – doc

21

这是无关紧要的。所有模板已经是inline - 更不用说,截至2012年,关键字inline的唯一用处是停止编译器对ODR违规行为的嘲讽。你是绝对正确的 - 你现在的编译器会知道自己的内联,甚至可以在翻译单元之间这样做。

+5

该标准没有声明所有模板都是内联的。 –

+10

@phresnel:但是模板与'inline'标记的函数具有相同的语义(也就是说,多个等价的定义可以传递给链接器,它将选择一个)。那不是内联,是inline关键字的真正功能。 –

+0

@BenVoigt:我知道'inline'的ODR含义。也许有人在我的答案下面(或以上,根据选择的排序)偷看。对于非专业模板,你当然是对的,但它在形式上是不一样的。 –

1

正如你所建议的,inline是编译器的暗示,仅此而已。它可以选择忽略它,或者实际上,内联没有标记为内联的函数。

使用inline与模板曾经是一个(穷)方式来解决问题,每个编译单元将为同一个模板类创建一个单独的对象,然后在链接时会导致重复问题。通过使用inline(我认为)这个名字在不同的链接时会碰到不同的名字冲突,但代价很大。  

Marshall Cline explains it here比我还好。

+0

@Xeo:以前并不这样。点击这里:http://gcc.gnu.org/onlinedocs/gcc-4.0.4/gcc/Template-Instantiation.html#Template-Instantiation我认为最近发生了变化,这就是为什么我用过去式说话的原因。 –

+1

@Xeo:您​​能否指出标准中标明函数模板总是内联的部分?因为,他们不是。 –

+0

@ phresnel:有趣的,我可以发誓我已经阅读过标准。也许我把它与功能模板从ODR中免除的事实混为一谈('§14.5.5.1p7&p8')。我的不好,我删除了错误的评论。 – Xeo