3

考虑以下示例(在同一翻译单元中):

inline void f();
void f() {}

重新声明时会发生什么ff还算inline不算?

我查看了这种情况的标准,但我只在 10.1.6/6 [dcl.inline] 中找到了它的反面:

[...] 如果函数或变量的定义在其第一次声明为内联之前出现在翻译单元中,则该程序格式错误。[...]

我想要标准中的一些参考资料,说明在这种情况下会发生什么。

我看到了这篇文章,但它没有在标准中显示明确的参考。我倾向于相信没有这样的参考。

4

2 回答 2

1

重新声明时会发生什么ff还算inline不算?

是的,f还在考虑inline中。

与函数说明符语义有关的标准相关部分inline可以在[dcl.fct.spec]中找到:

带有inline说明符的函数声明...声明了一个内联函数。说明inline符向实现表明,在调用点对函数体进行内联替换优于通常的函数调用机制。

内联函数应在使用 odr 的每个翻译单元中定义,并且在每种情况下都应具有完全相同的定义([basic.def.odr])。[注意:在其定义出现在翻译单元中之前,可能会遇到对内联函数的调用。—尾注] 如果函数的定义在其第一次声明为内联之前出现在翻译单元中,则该程序格式错误。如果具有外部链接的函数在一个翻译单元中声明为内联,则应在其出现的所有翻译单元中声明为内联;不需要诊断。inline具有外部链接的函数在所有翻译单元中应具有相同的地址。

[basic.def.odr]中:

每个程序都应包含该程序中 odr 使用的每个非内联函数或变量的准确定义

另请参阅[dcl.stc]/8中的示例:

void h();
inline void h();                // external linkage

inline void l();
void l();                       // external linkage

这一切的解释是:

  • inlineas 函数说明符充当标志,表示您希望内联对给定函数的调用。一旦在某个函数声明中遇到它,它就会为该特定函数重载保持“设置”状态,并且无法“取消设置”它。

  • 指定声明还是函数定义都没有关系inline,因为定义也是声明并且允许多个声明。 但是,说明符必须在函数定义之前函数定义之前以及在使用 odr之前遇到(odr-use意味着编译器需要实际发出调用函数的代码,或者出于任何原因需要其地址)。
    inline

  • 说明inline符对函数的链接没有影响,对于非静态全局函数,它仍然是外部的。如果一个inline函数(具有外部链接)的地址被占用,编译器将为其发出一个外联定义,确保链接器可以在必要时折叠多个定义(例如使用弱符号)。这样inline,不同 TU 中的函数地址将是相同的。

  • 一旦一个函数被声明inline并具有外部链接,它必须inline在所有其他使用它的翻译单元中声明。

  • 您必须inline在每个使用它的翻译单元中提供函数的定义,并且必须完全相同。

于 2018-01-20T14:11:37.797 回答
0

重新声明的效果在[basic.def]/1中指定

一个声明可以在翻译单元中引入一个或多个名称,或者重新声明先前声明引入的名称。如果是这样,则声明指定这些名称的解释和属性。[...]

因此,通过重新声明,可以将规范添加到名称中,但不能删除它们。

于 2018-01-20T11:23:01.407 回答