C ++内联重新声明

时间:2018-01-20 08:40:30

标签: c++ inline redeclaration

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

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

重新声明f时会发生什么? f是否仍被视为inline

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

  

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

我想在标准中引用一些参考资料来指明在这种情况下会发生什么。

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

2 个答案:

答案 0 :(得分:1)

  

重新声明f时会发生什么? f是否仍被视为inline

是的,f仍被视为inline

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

  

带有inline说明符的函数声明...声明了一个内联函数。 inline说明符指示实现在调用点处函数体的内联替换优先于通常的函数调用机制。

     

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

[basic.def.odr]

  

每个程序应该只包含每个非内联函数或该程序中使用的变量的一个定义

另见[dcl.stc]/8中的示例:

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

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

对所有这些的解释是:

  • inline作为函数说明符充当标志,表示希望对内联的给定函数进行调用。一旦在某个函数声明中遇到它,它仍然是" set"对于那个特定的函数重载,并且没有办法'#34; unset"它

  • 如果您在函数的声明定义上指定inline,则无关紧要,因为定义{{ 3}}一个声明,因为多个声明是is also 但是,inline说明符必须在之前使用函数的定义遇到 之前使用 em> odr-use 意味着编译器需要实际发出调用函数的代码,或者无论出于何种原因需要其地址。)

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

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

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

答案 1 :(得分:0)

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

中指定
  

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

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