当前位置:  开发笔记 > 编程语言 > 正文

constexpr头文件中的全局常量和odr

如何解决《constexpr头文件中的全局常量和odr》经验,为你挑选了1个好方法。

不幸的是,我有点困惑constexpr,在头文件中声明的全局常量和odr.

简而言之:我们可以从这里结束

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";

如果我想"只使用"那些全局声明/定义的实体并且不想考虑我如何使用它们,那么在头文件中定义全局变量?



1> Columbo..:

注意:从C++ 17开始,您可以将变量声明为内联.


TL; DR:如果您想要(非常)安全,请使用constexpr功能.它本身并不是必需的,如果你对这些对象进行琐碎的操作并且只关心它们的价值,或者根本不在下面列出的危险场景中使用它们,那肯定不是必需的.

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

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

在此输入图像描述

因为我们正在谈论,"以常数表达式初始化"肯定得到满足constexpr.所以"如果你不喋喋不休,那么对象在所有定义中都具有相同的价值D".

"对象没有使用"可能是唯一可疑的条件.基本上,它要求您不必将变量运行时存在作为符号,这反过来暗示了这一点

你没有将它绑定到引用(=>你不转发它!)

你没有(既不明确也不含蓄地)取其地址.

第二个规则的唯一例外是数组,只要上述两个规则没有违反产生的glvalue,就可以在下标操作中隐式获取地址.

更确切地说,odr-use由[basic.def.odr]/3管理:

除非应用左值到右值转换(4.1)以产生不调用任何非平凡函数的常量表达式(5.20),否则x其名称显示为可能已评估的表达式的变量将被ex使用.如果是object,是表达式的潜在结果集合的元素,其中左值到右值的转换(4.1)应用于或者是丢弃值表达式(第5节).exxxexeee

将ltr应用于任何constexpr变量将按照第一部分的要求运行.第二部分要求变量用作而不是实际对象 ; 也就是说,它最终被丢弃或直接评估,给出了上述经验法则.

如果你避免在内联函数,模板等内部使用变量,你就可以了.但是如果使用相应constexpr函数的返回值,则不必担心,因为prvalues已经表现得更像值/文字(而不是对象),constexpr函数是内联的,绝对不会违反ODR(如果你不在constexpr里面使用变量!).

推荐阅读
手机用户2502852037
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有