133

由于模板是在头文件中定义的,并且编译器能够确定内联函数是否有利,这是否有意义?我听说现代编译器更清楚何时内联函数并且忽略inline提示。


编辑:我想接受这两个答案,但这是不可能的。为了结束这个问题,我接受了Sebastian Mach的回答,因为它获得了大多数选票,而且他在形式上是正确的,但正如我在评论中提到的那样,我认为PuppyComponent 10的答案也是正确的,从不同的角度来看看法。

问题在于 C++ 语义,在inline关键字和内联的情况下并不严格。Sebastian Mach说“如果你是认真的,就写内联”,但实际上它的意思inline并不清楚,因为它从最初的含义演变为“停止编译器抱怨 ODR 违规”的指令,正如Puppy所说。

4

4 回答 4

105

这不是无关紧要的。不,不是每个函数模板都是inline默认的。该标准甚至在Explicit specialization ([temp.expl.spec])中对此进行了明确说明

有以下几点:

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/Josuttis 的C++ 模板:完整指南)。

于 2012-05-10T14:49:32.377 回答
41

这无关紧要。所有模板都已经inline- 更不用说截至 2012 年,该inline关键字的唯一用途是阻止编译器抱怨 ODR 违规。您是绝对正确的-您当前的编译器将自己知道要内联什么,甚至在翻译单元之间也可能这样做。

于 2012-05-10T14:05:07.153 回答
7

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

使用inline模板曾经是解决每个编译单元会为同一个模板类创建一个单独的对象的问题的(糟糕的)方法,这会导致链接时出现重复问题。通过使用inline(我认为)名称修饰的工作方式不同,它可以在链接时解决名称冲突,但会以大量臃肿的代码为代价。  

Marshall Cline在这里解释得比我还好。

于 2012-05-10T14:12:30.400 回答
-2

这就是 C++ 标准所说的:

[dcl.inline/1]

内联说明符仅应用于变量或函数的声明。

于 2020-10-22T20:08:24.837 回答