为什么不为C++ 17放弃一个定义规则?

Ric*_*rdo 4 c++ one-definition-rule c++17

引用C++草案N4713:

每个程序应该只包含每个非内联函数或变量的一个定义,该函数在该程序中在废弃语句之外使用(9.4.1); 无需诊断.该定义可以在程序中明确显示,可以在标准或用户定义的库中找到,或者(在适当的时候)隐式定义(见15.1,15.4和15.8).内联函数或变量应在每个翻译单元中定义,在翻译单元中,在废弃的语句之外使用它.

在C++ 17之前的C++版本中,我可以通过声明我的函数来解决这个限制inline.C++ 17为变量添加了相同的功能.

此外,在我看来,inline除了可以忽略ODR之外,-Keyword不会用于其他目的.

那么,为什么整个规则不会因为C++ 17而放弃呢?我无法看到可以关闭的规则的目的.

Bau*_*gen 13

"关闭"ODR inline不是免费的:inline实体的定义必须存在于每个翻译单元中.请注意,这意味着对其定义的任何更改都会导致重新编译使用它的每个编译单元.当函数是许多/大项目依赖的某些库的一部分时,这将特别令人不愉快.

inline另一方面,非函数仅存在于一个编译单元中,并且在其他地方需要时由链接器通过某些符号引用.遵守ODR可确保符号不含糊.

  • ODR并不保证**符号不含糊不清;****要求**它不含糊.负担在于程序员.不必诊断ODR违规,并且它们会导致未定义的行为.一个实际结果是,当您对"相同"函数有两个不同的定义时,您不知道哪个将被链接. (5认同)
  • ......并且所有翻译单元中的定义必须完全相同. (3认同)

Yak*_*ont 6

inline既危险又昂贵。

它很昂贵,因为现在使用某些东西的每个编译单元都取决于该东西的定义。那么改变身体吗?重新编译它的每个用户。

这是危险的,因为如果两个inline定义不一致,您的程序就是 IF-NDR(格式错误,无需诊断)。

如果没有inline,两个定义会导致程序格式错误,但编译器必须提供诊断;通常是硬错误。

inline关闭那个非常有用的警告。

如果每个编译器都能够将不同inline定义的 IF-NDR 转换为诊断错误消息,那么您就会遇到更多情况。只要这被证明是困难的和/或没有实现,inline就是“激活不安全模式!” 选项。将其设为默认值会适得其反。