头文件和odr中的constexpr全局常量 [英] constexpr global constants in a header file and odr

查看:217
本文介绍了头文件和odr中的constexpr全局常量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

不幸的是,我对constexpr,头文件中声明的全局常量和odr感到困惑.

Unfortunately, I am somewhat confused about constexpr, global constants declared in header files, and the odr.

简而言之:我们可以从这里得出结论

In short: Can we conclude from here

https://isocpp.org/files/papers/n4147.pdf

那个

constexpr MyClass const MyClassObj () { return MyClass {}; }
constexpr char const * Hello () { return "Hello"; }

优于

constexpr MyClass const kMyClassObj = MyClass {};
constexpr char const * kHello = "Hello";

用于在头文件中定义全局变量 如果我想仅在全球范围内使用" 声明/定义的实体,而又不想考虑如何如何使用它们?

for defining globals in a header file if I want to "just use" those globally declared/defined entities and do not want to think about how I use them?

推荐答案

注意:从C ++ 17开始,您可以声明

Note: as of C++17, you can declare your variables as inline.

TL; DR :如果您希望(非常)安全,请使用constexpr函数.但是,这并不是固有的必要,并且如果您要对这些对象执行琐碎的操作并且仅对它们的值感兴趣,或者根本不在下面列出的危险情况下使用它们,则肯定不是必需的.

TL;DR: If you want to be on the (very) safe side, go with constexpr functions. It isn't inherently necessary though, and certainly won't be if you're performing trivial operations on these objects and are solely interested in their value, or simply don't use them in the dangerous scenarios listed below.

基本问题是,诸如您的命名空间范围内的const变量(通常)具有内部链接( [basic.link]/(3.2)).这意味着编译相应标头的每个翻译单元将观察到一个不同的实体(即符号).

The fundamental issue is that const variables at namespace scope such as yours (generally) have internal linkage ([basic.link]/(3.2)). This implies that each translation unit compiling the corresponding header will observe a different entity (i.e. symbol).

现在,假设我们在使用这些对象的标头中具有模板或内联函数. ODR在这种情况下非常精确- [basic.def.odr]/6 :

Now imagine we have a template or inline function in a header using those objects. The ODR is very precise about this scenario - [basic.def.odr]/6:

用常量表达式初始化" 当然可以满足,因为我们在谈论constexpr.因此,如果您不介意的话,则该对象在D" 的所有定义中都具有相同的值.

"initialized with a constant expression" is certainly met, since we're talking constexpr. So is "the object has the same value in all definitions of D" if you don't monkey about.

对象不被滥用" 可能是唯一可疑的条件.基本上,它要求您不必将变量运行时作为符号存在,这反过来意味着

"the object isn't odr-used" is probably the only questionable condition. Basically, it requires that you don't necessitate the variables runtime existence as a symbol, which in turn implies that

  • 您不会将其绑定到引用(=>您不会转发它!)

  • You don't bind it to a reference (=> you don't forward it!)

您不会(既不明确也不隐含)获取其地址.

You don't (neither explicitly nor implicitly) take its address.

第二个规则的唯一例外是数组,只要所产生的glvalue不违反以上两个规则,就可以将其作为下标操作中的隐式地址.

The only exception to the second rule are arrays, which can be taken the address of implicitly inside a subscript operation as long as the two above rules aren't violated for the yielded glvalue.

更确切地说,odr的使用受 [basic.def.odr ]/3 :

More precisely, odr-use is governed by [basic.def.odr]/3:

其变量名称为可能评估的表达式ex的变量xex奇特使用,除非应用 从左值到右值(4.1)到x的转换将生成一个常量表达式(5.20),该常量表达式不会调用任何非平凡函数,并且如果x是对象,则ex是该集合的一个元素表达式e的可能结果,其中将左值到右值转换(4.1)应用于ee是舍弃值表达式(Clause 5).

A variable x whose name appears as a potentially-evaluated expression ex is odr-used by ex unless applying the lvalue-to-rvalue conversion (4.1) to x yields a constant expression (5.20) that does not invoke any non-trivial functions and, if x is an object, ex is an element of the set of potential results of an expression e, where either the lvalue-to-rvalue conversion (4.1) is applied to e, or e is a discarded-value expression (Clause 5).

将l-t-r应用于任何constexpr变量将按照第一部分的要求进行操作.第二部分要求将变量用作 value 而不是实际的 object ;也就是说,根据上述经验法则,它最终将被丢弃或直接评估.

Applying l-t-r to any constexpr variable will behave as required by the first part. The second part requires that the variable be used as a value rather than an actual object; that is, it's eventually either discarded or directly evaluated, giving the above rules of thumb.

如果您避免在内联函数,模板等内部使用odr,则可以.但是,如果您使用相应constexpr函数的返回值,则不必担心,因为prvalue已经表现得更像值/文字(不是对象),并且constexpr函数是内联的,并且绝对不会违反ODR(如果您不要在其中使用constexpr变量!)

If you avoid odr-use of the variable inside inline functions, templates or the like, you're fine. But if you use the return value of a corresponding constexpr function, you won't have to worry, since prvalues are already behaving more like values/literals (not objects) and constexpr functions are inline and definitely won't violate the ODR (if you don't use constexpr variables inside there!).

这篇关于头文件和odr中的constexpr全局常量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆