C/ c++头文件中的函数是禁止的吗?

Are functions in C/C++ headers a no-go?

本文关键字:函数 禁止 c++ 文件      更新时间:2023-10-16

我正在编写一段非常小的C/c++源代码。该程序从stdin读取输入值,用算法处理它们,并将结果写入stdout。

我只是在一个文件中实现所有这些,但我也想要算法的测试用例(不是输入/输出读取),所以我在我的项目中有以下文件:

  • main.cpp
  • sort.hpp
  • sort_test.cpp

我立即在sort.hpp中实现了算法,而不是sort.cpp。它很短,没有任何依赖项。

你会说,在某些情况下,在头文件中定义的函数是可以的,即使它们是复杂的算法,而不仅仅是简单的访问/mutator ?或者有什么我应该避免的理由吗?什么时候我应该将代码从头文件移动到源文件?

在头文件中使用函数没有什么错,只要您了解权衡。将它们放在头文件中意味着它们必须在包含头文件的任何翻译单元中进行编译(和重新编译)。(并且它们必须声明为inline,否则您将得到链接器错误。)

在有许多翻译单元的项目中,如果您经常这样做,可能会导致编译时间明显减慢。

另一方面,它确保函数定义在调用函数的任何地方都是可见的——这意味着它可以简单地内联,因此结果程序可能运行得更快。

最后,对于函数模板,您通常没有实际的选择。定义必须在调用站点可见,实现这一点的唯一实际方法是将其放在标题中。

最后要考虑的是,头文件库更容易部署和使用。你不需要链接任何东西,你不需要担心ABI或其他任何东西。你只需要将标题添加到你的项目中,包括它们,然后就可以开始了。

相当多的流行库使用仅头文件策略。

当你把函数放在头文件中,你必须确保声明它们是inline。当多个.cpp文件包含该头文件时,需要这样做来避免重复定义警告。一般来说,你应该只把小函数放在头文件中,因为它将为每个包含头文件的cpp文件编译,这将减慢编译时间,也会导致代码膨胀;较大的可执行文件。

可以将任何函数放在标题中,只要它是inline。诸如在class { }和模板中定义的函数之类的东西是隐式的inline

如果结果应用程序变得太大,那么优化代码大小。在出现问题之前进行优化是一种反模式,特别是当"按照您的方式"进行优化有好处时,并且修复方法很简单,只需从一个文件移动到另一个文件并删除inline即可。

当然,如果您想将代码作为库分发,那么在头文件、静态库文件还是动态库二进制文件之间做出决定是一个影响用户的重要决定。

绝大多数boost库都是只支持头文件的,所以我想说:是的,这是一种公认的实践。只是别忘了inline .

这确实是一个风格选择。但是把它放在标题中确实意味着它将是内联代码而不是函数。如果需要相同的功能,可以使用内联关键字:

inline int max(int a, int b)
{
  return (a > b) ? a : b;
}

http://en.wikipedia.org/wiki/Inline_function

一般情况下(对于非内联函数)应该避免这样做的原因是,多个源文件将包含您的头文件,从而产生链接器错误。如果你有一个pramga一次或类似的技巧-如果你有多个编译单元(例如cpp文件)包括相同的头文件,复制将显示出来。

如果你想内联函数,它必须在header中,否则它不能被内联。

如果你发布了一个带有库的头文件,头文件中有一些实现,你可以肯定,几年后如果你改变了实现,它的工作方式和以前不完全一样,一些人的代码会崩溃,因为他们会依赖于他们在头文件中看到的实现。是的,我知道一个人不应该这样做,但很多人确实在头文件中寻找实现和其他行为,他们可以以一种意想不到的方式利用/使用,以克服他们遇到的一些问题。

如果你打算使用模板,那么你别无选择,只能把它全部放在header中。(如果你的编译器支持导出模板,这可能不是必要的,但我知道只有一个)。

在header中实现是可以的。这取决于你需要什么。如果你把定义分离到一个不同的文件中,那么编译器会创建带有外部链接的符号,如果你不想,你可以在头文件本身中定义函数。但是您会为代码段浪费一些内存。如果你把这个头文件包含在两个不同的文件中,那么这两个文件代码段都有这个函数定义。

如果其他头文件将具有类似名称的函数,那么这将是一个问题。然后你必须使用inline