使用指针进行constexpr初始化

14

我试图使用一个指向int的const对象来初始化一个constexpr声明。同时,我还尝试使用一个非const类型的对象来定义一个对象。

代码:

#include <iostream>

int main()
{
constexpr int *np = nullptr; // np is a constant to int that points to null;
int j = 0;
constexpr int i = 42; // type of i is const int
constexpr const int *p = &i; // p is a constant pointer to the const int i;
constexpr int *p1 = &j; // p1 is a constant pointer to the int j; 
}

g++ 日志:

constexpr.cc:8:27: error: ‘& i’ is not a constant expression
constexpr.cc:9:22: error: ‘& j’ is not a constant expression

我认为这是因为主函数中的对象没有固定的地址,所以g++会向我返回错误信息;我该如何纠正这个问题呢?不使用字面类型。


@chris 你能再解释一下你的观点吗?constexpr 的整个重点在于它是在编译时定义的,主要使用字面类型(它们是例外)。我的观点是函数内的对象被分配了临时地址(出于显而易见的原因)。在这里,g++会由于这些临时内存地址向我抛出错误消息。我该如何声明一个不会这样做的函数(即,在控制流期间允许所有对象都固定)? - TheBlueCat
我非常怀疑你能够将地址或指针与constexpr关联起来。 - chris
请注意,此处不能使用字面类型。 - Jesse Good
@JesseGood 你还有什么其他方法可以强制进行编译时评估呢? - TheBlueCat
1
不幸的是,这个例子在VS 2015中运行良好。微软真可怜。 - Lukáš Bednařík
显示剩余3条评论
1个回答

22

将它们设为静态(static)以修复它们的地址:

int main()
{
  constexpr int *np = nullptr; // np is a constant to int that points to null;
  static int j = 0;
  static constexpr int i = 42; // type of i is const int
  constexpr const int *p = &i; // p is a constant pointer to the const int i;
  constexpr int *p1 = &j; // p1 is a constant pointer to the int j; 
}

这被称为地址常量表达式[5.19p3]:

地址常量表达式是指评估为指向具有静态存储期的对象的地址,函数的地址或空指针值的指针类型的prvalue核心常量表达式,或std :: nullptr_t类型的prvalue核心常量表达式的常量表达式。


1
静态变量的地址不是在编译时定义的吗?而是在链接时定义的? - anton_rh
@anton_rh:是的,地址在链接时确定。但这并不与我上面的答案冲突。 - Jesse Good
2
@JesseGood 我认为这是一个值得阐述的好点子。 constexpr 可以在编译后解决为一个值。 - sh1
如果您查看实现,那么您会发现实际上发生的是编译器将生成一个常量+链接器引用,以便相对于链接地址修正常量。 - Goswin von Brederlow

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接