是否保证只有一个非内联内联函数的副本?
Is there guaranteed to be only a single copy of a non-inlined inline function?
如果我声明一个内联的大函数,而编译器选择将它编译为一个独立的函数,是否保证程序中只有一个非内联内联函数的副本,或者编译器可能最终在不同的翻译单元中创建此函数的多个非内联副本?
或者,以几乎肯定会引起很多咬牙切齿的方式重新表述:在预处理时间不是问题的情况下,在头文件中定义一个大的内联方法是一种有效的方法重用该代码而不必 compile/link 在单独的翻译单元中?
我建议您完成以下问题:
"inline" keyword vs "inlining" concept
出于优化目的,如果 inline
函数是:
- 足够大,然后编译器可能不会做"inlining"
- 足够短,然后编译器可能做"inlining"
然而,在这两种情况下,One Definition Rule (ODR) 是有保证的,因为您使用了 inline
关键字。
If I declare a large function inline, and the compiler chooses to compile it as a standalone function anyway, is there guaranteed to be only a single copy of that non-inlined inline function in the program,
没有。没有这样的保证。 保证的是,函数中声明的任何静态变量只会有一个副本,并且如果你获取函数的地址,你将始终获得相同的值.
or might the compiler end up creating multiple non-inlined copies of this function in different translation units?
有可能。它们甚至可能不相同:如果它可以看到参数在一个翻译单元中始终为空,则可以省略 if (arg != nullptr
)...`.
的代码
你需要在这里非常具体,因为你要求保证。 C++ 标准对程序行为做出保证,而不是对实现做出保证,即使那样也不是为了防止恶意编译器而编写的。许多实现细节都受到行为的有效约束。但不完全。
编译器可以自由地在您的可执行文件中嵌入任何函数的 2^17 个不同副本,无论是否内联。这将毫无意义,但标准并没有禁止它!静态变量的值和地址必须共享,因为这是可观察的,并且如果 C++ 代码可以访问它们,则指向每个函数的所有函数指针都必须比较相等(它们可以具有地址的不同二进制表示,只是改变==
!]的意思。
这会发生吗?不,但你要求保证。 C++ 标准为实现者留下了巨大的空间。实施质量意味着现代编译器不会经常做愚蠢的事情。
实际上,在每个使用它的 .o
文件中创建一个内联函数。它被标记为特殊 ("weak")。静态链接时,这些副本中除了一个以外的所有副本都将被丢弃。保留哪一个取决于链接顺序,并且可能因构建而异(尤其是部分构建)。只有一份静态局部变量以类似的方式保存。 中所有指向函数或静态局部变量的指针必须 在运行时比较相等。
动态链接导致某些编译器在构建到 dll 中时将其丢弃。加载 .so
时,其他编译器会查看符号是否已加载,如果已加载则不加载 .so
中的副本。动态链接是函数的多个副本最有可能继续存在并被访问的情况。如果这种情况没有发生,您就清楚了,如果是,请对其进行测试。 C++ 标准没有描述动态链接。
如果我声明一个内联的大函数,而编译器选择将它编译为一个独立的函数,是否保证程序中只有一个非内联内联函数的副本,或者编译器可能最终在不同的翻译单元中创建此函数的多个非内联副本?
或者,以几乎肯定会引起很多咬牙切齿的方式重新表述:在预处理时间不是问题的情况下,在头文件中定义一个大的内联方法是一种有效的方法重用该代码而不必 compile/link 在单独的翻译单元中?
我建议您完成以下问题:
"inline" keyword vs "inlining" concept
出于优化目的,如果 inline
函数是:
- 足够大,然后编译器可能不会做"inlining"
- 足够短,然后编译器可能做"inlining"
然而,在这两种情况下,One Definition Rule (ODR) 是有保证的,因为您使用了 inline
关键字。
If I declare a large function inline, and the compiler chooses to compile it as a standalone function anyway, is there guaranteed to be only a single copy of that non-inlined inline function in the program,
没有。没有这样的保证。 保证的是,函数中声明的任何静态变量只会有一个副本,并且如果你获取函数的地址,你将始终获得相同的值.
or might the compiler end up creating multiple non-inlined copies of this function in different translation units?
有可能。它们甚至可能不相同:如果它可以看到参数在一个翻译单元中始终为空,则可以省略 if (arg != nullptr
)...`.
你需要在这里非常具体,因为你要求保证。 C++ 标准对程序行为做出保证,而不是对实现做出保证,即使那样也不是为了防止恶意编译器而编写的。许多实现细节都受到行为的有效约束。但不完全。
编译器可以自由地在您的可执行文件中嵌入任何函数的 2^17 个不同副本,无论是否内联。这将毫无意义,但标准并没有禁止它!静态变量的值和地址必须共享,因为这是可观察的,并且如果 C++ 代码可以访问它们,则指向每个函数的所有函数指针都必须比较相等(它们可以具有地址的不同二进制表示,只是改变==
!]的意思。
这会发生吗?不,但你要求保证。 C++ 标准为实现者留下了巨大的空间。实施质量意味着现代编译器不会经常做愚蠢的事情。
实际上,在每个使用它的 .o
文件中创建一个内联函数。它被标记为特殊 ("weak")。静态链接时,这些副本中除了一个以外的所有副本都将被丢弃。保留哪一个取决于链接顺序,并且可能因构建而异(尤其是部分构建)。只有一份静态局部变量以类似的方式保存。 中所有指向函数或静态局部变量的指针必须 在运行时比较相等。
动态链接导致某些编译器在构建到 dll 中时将其丢弃。加载 .so
时,其他编译器会查看符号是否已加载,如果已加载则不加载 .so
中的副本。动态链接是函数的多个副本最有可能继续存在并被访问的情况。如果这种情况没有发生,您就清楚了,如果是,请对其进行测试。 C++ 标准没有描述动态链接。