内联函数解决多定义是一个定义明确的事情吗?

时间:2016-01-18 07:40:36

标签: c++ c++11 inline

我正在构建一个仅模板化标头的C ++ 11库。正如我所读到的,我应该将我的成员函数定义为inline,以保证翻译单元中不会出现多个定义。

这是inline关键字的明确定义吗?我曾经认为inline与性能有关。我怀疑通过使用inline来实现此目的就像打开后门一样。使用它的任何缺点?任何其他解决方案?

3 个答案:

答案 0 :(得分:7)

如果您阅读例如this inline reference您将看到具有外部链接的函数的属性列表,第二点说:

  

每个翻译单元都有相同的地址。

这意味着将函数声明为inline将导致所有translation units中只存在该函数的一个实例(即从源文件生成的所有目标文件)。

由于只存在一个函数实例,因此不会出现任何多重定义错误。

答案 1 :(得分:3)

Joachim的问题回答了关于内联语义的主要问题,但OP也提出了使用内联的缺点。执行内联时通常的权衡取决于代码大小和速度。我们有两个案例:

  1. 该功能实际上是内联的。在这种情况下,正在复制正文,增加最终程序的代码大小。这还可能包括性能损失,因为将程序代码缓存在处理器缓存中变得更加困难。

  2. 该功能未内联。我假设一个带有外部链接的内联函数。在这种情况下,链接器将删除除一个之外的所有副本,以确保函数的地址在整个程序中是唯一的。此过程可能会降低构建过程的速度。在msvc< = 2010上,这曾经是一个主要问题,因为链接器是单线程的并且死得很慢。

  3. 必须在使用它们的每个编译单元中解析和编译内联函数。这可能会减慢构建过程。

  4. 更好的方法可能是使用整个程序优化,编译器可以在编译单元之间进行优化。所有主要的编译器都支持这一点。

答案 2 :(得分:3)

就标准而言,inline关键字的唯一重要性是为了防止多个定义出错。

一旦你在多个翻译单元中定义了函数,编译器可以在每个翻译单元中包含该函数的副本(尽管他们必须确保将函数的地址赋予单个,唯一的,结果),他们可能决定在每个呼叫站点扩展功能(或者他们可能不会)。

如果您想要一个仅限标题的库,则将成员标记为inline(使用关键字,或者通过在类的主体中定义它们)是必需的。仅头文件库的优点是它易于使用,缺点是编译客户端可能需要更长时间,而更改它时可能需要重新编译更多。