C++中的内联函数和普通函数之间的区别

3

我刚刚完成了Bruce Eckel的《C++编程思想》中的内联函数章节。其中有一个练习要求你创建两个完全相同的函数,一个是内联函数,另一个不是。然后使用clock()函数计算每个函数执行所用的时间。我曾经处理过类似的问题,我认为这并不复杂。因此,我得出了以下结论:

#include <iostream>
#include <ctime>
using namespace std;

inline int infun(int x) {
    x = 3;
    x = 5;
    cout << "";
    return x;

}

int fun(int x) {
    x = 3;
    x = 5;
    cout << "";
    return x;

}

int main() {

    clock_t startIn = clock();
    for (int i = 0; i < 10000000; i++) {
        infun(i);

    }
    clock_t finishIn = clock();

    clock_t start = clock();
    for (int i = 0; i < 10000000; i++) {
        fun(i);

    }
    clock_t finish = clock();

    clock_t startIn2 = clock();
    for (int i = 0; i < 10000000; i++) {
        infun(i);

    }
    clock_t finishIn2 = clock();

    cout << "Inline: " << (finishIn - startIn) << endl << "Regular Function: "
            << (finish - start) << endl<< "Second Inline: " << finishIn2 - startIn2 << endl;
    return 0;
}

输出

Inline: 195842
Regular Function: 166564
Second Inline: 162917

我有三个函数。其中两个是完全相同的内联函数,另一个是非内联函数(为了测试目的而创建这种情况)。

a) 为什么第一个内联函数需要那么长时间(对于任何首次执行的函数都是如此) b) 如果重复次数减少(比如1000),普通函数比其他函数更快。

即使是更简单的函数也能满足我的测试用例:

inline int infun(int x) {
    return x; 
}

我还检查了汇编输出,以确保这些内联函数确实是内联的或者g++没有将非内联函数提升为内联函数。感谢您的时间,欢迎任何反馈。


3
你使用了哪些编译选项?测量未经优化的构建不会提供正确的信息。 - NathanOliver
inline只是一种建议,编译器会自行决定是否实际内联代码。此外,缓存效应可能会导致完全相同的代码在时间上有所不同。标准的clock也有很多细节,你可能会看到一个并不存在的巨大差异。 - Mark Ransom
感谢您的输入,我已经使用了Eclipse的自动生成编译选项,并且刚刚测试了没有任何选项的g ++。结果相同。作者尚未提到任何特殊的构建选项。另外,到目前为止,书中练习的概念更多地是对理论的一些有趣体验(不是真正的特殊问题)。结果必须像理论一样坚实,在发生冲突的情况下,作者可能会问为什么。 - fllprbt
@Barmar:现代编译器最好不要忽略这个关键字,否则你的程序可能会因为重复定义而无法编译。然而,它们在优化器中可能不会考虑它。 - celtschk
@fllprbt - 如果你使用g++没有选项,那么时间并不重要。除非你要求编译器优化代码并使其快速,否则它甚至可能不会考虑内联内联函数。这就像Usain Bolt走路而不是跑步一样。 - Bo Persson
显示剩余2条评论
1个回答

5

从cppreference.com的内容中改编:

内联函数是具有以下属性的函数:

1) 可以有多个定义,只要每个定义出现在不同的翻译单元中。例如,内联函数可以在多个源文件中 #include 的头文件中定义。

2) 内联函数的定义必须存在于访问它的翻译单元中(不一定是在访问点之前)。

3) 具有外部链接的内联函数(如未声明为 static)具有以下附加属性:

1) 它必须在每个翻译单元中声明为内联函数。 2) 它在每个翻译单元中具有相同的地址。

请注意,优化、性能或实际机器代码内联从未被提及或暗示过。

inline只是告诉编译器:“该函数可能被定义多次,但我保证每个定义都是相同的”


感谢您的评论。这本书多次提出了效率问题,甚至提出了何时使用内联以提高效率的建议。这也是这个练习的核心,找出哪一个更快。 - fllprbt
@fllprbt,“inline”在C++中的含义已经发生了变化,简单来说:编译器不会仅仅因为你标记了“inline”就将函数内联。在C++中,“inline”的唯一目的是告诉编译器一个函数定义在翻译单元之间是相同的。 - Mário Feroldi
1
@fllprbt 我来详细解释一下我的评论。我快速浏览了你提到的那本书,它是在将近20年前写的。当时,有很多C程序员认为他们懂C++(但实际上并不懂)。可以说,C++标准当时还没有今天成熟。这种混淆是可以理解的。然而,如果Eckel先生仍在教学,他应该提高自己的水平和/或修订他的书。它会误导人们。 - Richard Hodges
@RichardHodges 这本书是我的论文导师建议的,他肯定与一个更早的时期有关。最近我发现它并不那么好,但这个问题让我真正开始考虑改变。感谢您的反馈。 - fllprbt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接