c++11中的constexpr概念

Posted

技术标签:

【中文标题】c++11中的constexpr概念【英文标题】:constexpr concept in c++11 【发布时间】:2018-08-09 12:02:27 【问题描述】:

我打算了解 C++ 中 constexpr 的概念。我的理解是 constexpr 在编译时被评估。在here 中,我找到了一个他们有以下sn-p 的示例。

int z[30];

constexpr auto e2 = &z[20] - &z[3];

他们在编译时计算地址之间的差异。当我们不知道编译时地址的实际值时,如何在编译时对其进行评估?

【问题讨论】:

编译器是怎么知道的?内存在运行时分配在堆栈中的某个位置。 哦,好吧,我现在明白了.. 编译器知道地址之间的区别而不是实际地址。当我制作 const auto e2 = &z[20];它会引发错误。 【参考方案1】:
constexpr auto e2 = &z[20] - &z[3]; 

只计算第三个和第 20 个元素之间的偏移量。所以不需要知道地址。

另一方面,以下示例不起作用,因为z[20]t 的地址是在运行时评估的。

int z[30];
int t;
constexpr auto e2 = &z[20] - &t;

正如Passer By 所指出的,根据标准,这是未定义的行为(7.6.6 Additive operators,最后一句):

除非两个指针都指向同一个数组对象的元素,或者 超过数组对象的最后一个元素,行为未定义。

【讨论】:

&z[20] - &t 是未定义的行为。【参考方案2】:

编译器不需要知道地址的实际值。它采用简单的指针算法。由于 z 是一个整数数组,所以数组中两个整数地址相减将产生下标之间的差异。

所以

constexpr auto e2 = &z[20] - &z[3];

将导致将值 17 分配给 e2。

【讨论】:

就在我发布我的答案时,我收到了一个通知,说已经发布了一个答案。那我应该删除这个答案吗?【参考方案3】:

编译器然后汇编器生成机器代码和变量地址。地址可以是绝对的,也可以是可重定位的。当加载器将它们放入内存段或当它们在内存中时,地址必须被固定。所有 constexpr 都说您可以在编译时评估这些东西,是的,您可以。有地址。有一个价值。机器代码或可执行代码将在后台使用基于操作系统的新偏移量的地址进行更新。程序员不再担心 16 位实际系统上的绝对寻址。程序员只需要知道这个过程是如何真正工作的。

数组在内存中是连续的,因此即使使用相对寻址,它们之间的距离也将是 N 个字节......确实是一个非常恒定的表达式,哈哈

【讨论】:

什么是“十六进制字节”? @LightnessRacesinOrbit 抱歉让您感到困惑

以上是关于c++11中的constexpr概念的主要内容,如果未能解决你的问题,请参考以下文章

为啥右值不能分配给 constexpr 引用变量

C++11 中的 ConstExpr 对象中的可变成员

constexpr 具有未触及的非 constexpr 参数:谁是正确的,clang 还是 gcc?

字符串文字与整数中的C ++ constexpr vs宏

C++11新特性:17—— C++11 constexpr和const的区别

c++11:为啥静态 constexpr 的类内初始化不是定义?