1

如果我声明一个大函数内联,并且编译器无论如何都选择将其编译为独立函数,那么是否保证程序中只有该非内联内联函数的一个副本,或者编译器最终可能会创建多个非内联函数- 这个函数在不同翻译单元中的内联副本?

或者,以一种几乎肯定会引起咬牙切齿的方式重新表述:在不考虑预处理时间的情况下,在头文件中定义一个内联的大型方法是一种能够重用该代码而无需在单独的翻译单元中编译/链接?

4

3 回答 3

3

您需要在这里非常具体,因为您要求保证。C++ 标准对程序行为做出保证,而不是对实现做出保证,即便如此,它也不是为了防止恶意编译器而编写的。许多实现细节受到行为的有效约束。但不完全。

编译器可以自由地将任何函数的 2^17 个不同副本嵌入到您的可执行文件中,无论是否内联。这毫无意义,但标准并没有禁止它!静态变量的值和地址必须共享,因为这是可观察到的,并且如果 C++ 代码可以获取它们,则指向每个函数的所有函数指针都必须比较相等(它们可以具有地址的不同二进制表示,只是改变做 a 的意思==!)。

这会发生吗?不,但你要求保证。C++ 标准为实现者留下了巨大的自由度。实现的质量意味着现代编译器不会经常做愚蠢的事情。

实际上,在每个.o使用它的文件中都会创建一个内联函数。它被标记为特殊(“弱”)。静态链接时,除了其中一个副本之外的所有副本都将被丢弃。保留哪一个将取决于链接顺序,并且可能因构建而异(尤其是部分构建)。只有一个静态局部变量的副本以类似的方式保存。所有指向函数或静态局部变量的指针在运行时必须比较相等。

动态链接会导致一些编译器在构建到 dll 时丢弃它。其他编译器在.so加载.so. 动态链接是最有可能函数的多个副本继续存在并被访问的情况。如果这种情况没有发生,您很清楚,如果是,请对其进行测试。C++ 标准没有描述动态链接。

于 2016-10-14T11:01:47.280 回答
3

如果我声明了一个大函数内联,并且编译器无论如何都选择将其编译为独立函数,那么是否保证程序中只有该非内联内联函数的一个副本,

不,没有这样的保证。可以保证的是,函数中声明的任何静态变量都只会有一个副本,并且如果您获取函数的地址,您将始终获得相同的值。

还是编译器最终会在不同的翻译单元中创建该函数的多个非内联副本?

它可能。它们甚至可能不相同:如果它可以看到参数在一个翻译单元中始终为空,它可以省略if (arg != nullptr)...` 的代码。

于 2016-10-14T10:24:22.890 回答
0

我建议您通过以下问题:
“内联”关键字与“内联”概念

出于优化目的,如果inline函数是:

  • 足够大,那么编译器可能不会做“内联”
  • 足够短,那么编译器可能会做“内联”

但是,在这两种情况下,都可以保证一个定义规则 (ODR),因为您使用了inline关键字。

于 2016-10-14T10:12:18.443 回答