简体   繁体   English

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

[英]Why isn't the one definition rule abandoned for C++17?

Citing C++ Draft N4713: 引用C ++草案N4713:

Every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program outside of a discarded statement (9.4.1); 每个程序应该只包含每个非内联函数或变量的一个定义,该函数在该程序中在废弃语句之外使用(9.4.1); no diagnostic required. 无需诊断。 The definition can appear explicitly in the program, it can be found in the standard or a user-defined library, or (when appropriate) it is implicitly defined (see 15.1, 15.4 and 15.8). 该定义可以在程序中明确显示,可以在标准或用户定义的库中找到,或者(在适当的时候)隐式定义(见15.1,15.4和15.8)。 An inline function or variable shall be defined in every translation unit in which it is odr-used outside of a discarded statement. 内联函数或变量应在每个翻译单元中定义,在翻译单元中,在废弃的语句之外使用它。

In C++ versions prior to C++17, I can get around this restriction by just declaring my functions inline . 在之前的C ++ 17 C ++版本,我可以只是说出我的功能绕开这个限制inline C++17 adds the same feature for variables. C ++ 17为变量添加了相同的功能。

Furthermore, it seems to me that the inline -Keyword does not serve another purpose apart from making it possible to ignore the ODR. 此外,在我看来, inline -Keyword除了可以忽略ODR之外不会用于其他目的。

So, why isn't this whole rule just abandoned for C++17 ? 那么,为什么整个规则不会因为C ++ 17而放弃呢? I can't see the purpose of a rule that can be turned off. 我无法看到可以关闭的规则的目的。

"Turning off" the ODR with inline is not free: the definition of an inline entity must be present in every translation unit. 使用inline “关闭”ODR并不是免费的: inline实体的定义必须存在于每个翻译单元中。 Note that this implies that any change to its definition causes re-compilation of every compilation unit that uses it. 请注意,这意味着对其定义的任何更改都会导致重新编译使用它的每个编译单元。 This would be particularly unpleasant when the function is part of some library many / big projects depend upon. 当函数是许多/大项目依赖的某些库的一部分时,这将特别令人不愉快。

Non- inline functions, on the other hand, live in just one compilation unit and are referenced via some symbol by the linker when needed elsewhere. 另一方面,非inline函数只存在于一个编译单元中,并且在其他地方需要时由链接器通过某个符号引用。 Complying with the ODR guarantees that symbol is not ambiguous. 遵守ODR可确保符号不含糊。

inline is dangerous and expensive. inline是危险和昂贵的。

It is expensive because every compilation unit that uses something now depends on the definition of the thing. 它很昂贵,因为现在使用某些东西的每个编译单元都取决于该东西的定义。 So change the body? 那么改变身体? Recompile every user of it. 重新编译它的每个用户。

It is dangerous because if two inline definitions disagree, your program is IF-NDR (ill formed, no diagnostic required). 这很危险,因为如果两个inline定义不一致,那么您的程序就是IF-NDR(形成错误,无需诊断)。

Without inline , two definitions cause an ill formed program, but the compiler must provide a diagnostic; 如果没有inline ,两个定义会导致生成错误的程序,但编译器必须提供诊断; usually a hard error. 通常是一个硬错误。

inline turns off that extremely useful warning. inline关闭了这个非常有用的警告。

If every compiler was capable of converting the IF-NDR of different inline definitions into a diagnostic error message you'd have more of a case. 如果每个编译器都能够将不同inline定义的IF-NDR转换为诊断错误消息,那么您将拥有更多案例。 So long as that proves difficult and/or not implemented, inline is a "activate unsafe mode!" 只要这证明很难和/或没有实现, inline就是“激活不安全模式!” option. 选项。 Making it default would be counter productive. 将其设为默认值会适得其反。

The trade-off is that you need the definition of an inline function everywhere it's used. 权衡是你需要在任何地方使用inline函数的定义。 If you want that, just put your whole program in a single .cpp file. 如果你想要,只需将整个程序放在一个.cpp文件中。

The ODR is what you need to have separate compilation, and that is still useful. ODR是您需要单独编译的,这仍然很有用。

From cppreference : cppreference

One and only one definition of every non-inline function or variable that is odr-used (see below) is required to appear in the entire program (including any standard and user-defined libraries). 每个非内联函数或变量使用的一个且仅有一个定义(见下文)需要出现在整个程序中(包括任何标准和用户定义的库)。 The compiler is not required to diagnose this violation, but the behavior of the program that violates it is undefined. 编译器不需要诊断此违规,但是违反它的程序的行为是未定义的。

Declaring a function as inline does not "ignore" ODR, but it causes each appearance of the function to be its own entity that needs a definition in each translation unit where it is used. 将函数声明为inline不会“忽略”ODR,但它会导致函数的每个外观都是其自己的实体,需要在每个使用它的转换单元中定义。 Small, but significant difference. 虽然小而重要但差异很大。 ODR is still required to have seperate translation units. ODR仍然需要有单独的翻译单位。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM