头文件中的代码将始终内联?

时间:2010-07-27 10:49:20

标签: c++ inline

我刚与同事讨论了头文件中的代码:

他说,头文件中定义的代码将始终由编译器内联(如我的示例头中的函数GetNumber()中的代码)。我说有时,只要编译器决定这样做,它就会被内联。那么我们哪一个人必须带上一块蛋糕才能说出肮脏的谎言?或者也许我们都错了......?

MyClass.hpp

   class MyClass
    {
    public:
    MyClass();
    ~MyClass();

    int GetNumber() const 
    {
     //...; 
     return m_number;
    };

    private:
    int m_number;
    };

7 个答案:

答案 0 :(得分:12)

在类中定义的任何函数(如GetNumber示例)而不是刚刚声明的函数是隐式inline。这意味着它与使用inline关键字无关,因此由于这些函数的多个定义,标题的多个包含不会导致链接错误。

大多数现代编译器都将inline视为链接命令,仅此而已。有些编译器提供了更强大的关键字,例如CL __forceinline,这意味着'如果可以的话,可以内联这个'。

所以你们两个都是正确的,而且都是错误的。

答案 1 :(得分:7)

你的朋友错了,你是对的。

内联不取决于代码的位置(标头与否)。预处理后,没有标题或非标题。整个单元是一个单独的文件,它包含所有包含的东西。

尝试运行gcc预处理器,然后你会看到:

gcc -E some_source_file_with_includes

答案 2 :(得分:4)

实际上两者都是正确的。你们的意思是有点不同。 (我猜)

来自内联函数的C ++标准文档,

  
      
  1. 功能声明(8.3.5,9.3,   11.4)使用内联说明符声明内联函数。
  2.         

    <强> 2。在类中定义的函数       定义是内联函数。

正如你的同事所说,确实是内联函数

但内联函数的代码替换而不是正常的函数调用取决于编译器。 (我希望这就是你的意思)即使编译器没有替换它仍然是一个内联函数。

希望它能解决你的担忧..

答案 3 :(得分:3)

这取决于“内联”的含义。如果在头文件中定义了某些内容,它将被单独编译到包含它的每个编译单元中。是否内联的任何调用将由编译器决定。

答案 4 :(得分:2)

类成员函数定义 (与声明的相反)在类定义中 隐式 inline。标头中的其他代码不是。

您可以轻松地检查:创建一个带有标题和两个实现文件的小型C ++项目,定义一个函数

void print(std::ostream& os)
{
  os << "Hello, world!\n";
}
标题中的

并在两个实现文件中包含该标头。链接器现在会抱怨函数定义了两次。在函数定义之前放置inline,错误将消失。

然而,还有一些违规行为。例如,常量定义将自动获得外部链接。因此,一个

const int answer = 42;
标题中的

不会让链接器抱怨answer的多个定义,而

int question;

意愿。

答案 5 :(得分:1)

这不是真的,如果在类声明中指定,则只会内联成员函数中的代码(如果编译器决定这样做)。它必须允许定义成员,因此它们可能被声明为C的static(它将允许在编译单元中使用,但不能链接到其他目标文件),这将在每个目标文件中放置一个版本。自己尝试一下,你会注意到除非你为类声明之外的任何东西指定inline关键字,否则你会得到重复。

答案 6 :(得分:1)

编译器决定。即使使用_inline也只是告诉编译器您更喜欢内联代码,但编译器的成本/收益分析器可以做出其他决定。

如果您使用Microsoft C++来使代码内联,则可以使用_forceinline,但这可能会导致更大的二进制文件。