严格按照C ++ 14的规则,至少cppreference.com给出的规则,不是第(1)行是一个常量表达式吗?
constexpr const int* addr(const int& ir) { return &ir; }
constexpr const int* tp = addr(5); // (1)
确实不是地址常量表达式,因为&ir
不是静态对象的地址(&ir
是此上下文中的临时地址,在编译时无法知道。
但它是一个核心常量表达式,因为它没有违反任何后面列出的核心常量表达式的规则,它没有关于后面列出的规则获取对象的地址。
答案 0 :(得分:6)
不,addr(5)
不是常量表达式,因此发布的代码格式错误。是的,你是正确的addr(5)
是核心常量表达式。
我可以看到为什么你可以单独从cppreference页面思考核心常量表达式,整数常量表达式,转换常量表达式,文字常量表达式,引用常量表达式和地址常量表达式都是常量表达式的类型。但真正的定义在C ++ 14 [expr.const] / 4:
中给出常量表达式是一个glvalue核心常量表达式,其值是指具有静态存储持续时间的对象或函数,或者是一个prvalue核心常量表达式,其值是一个对象,其中,对象及其子对象:
引用类型的每个非静态数据成员引用具有静态存储持续时间或函数的对象,
如果对象或子对象是指针类型,则它包含具有静态存储持续时间的对象的地址,该对象的地址超过此类对象的结尾,函数的地址或空指针值。 / p>
作为“核心常数表达”并没有太多直接影响;它只是一个术语,用于帮助定义“整数常量表达式”,“转换常量表达式T
”和“常量表达式”。而“常量表达式”实际上描述了“核心常量表达式”描述的表达式的子集,而不是超集。
例如,要完成,使示例格式错误的段落([dcl.constexpr] / 9)需要一个常量表达式,而不是核心常量表达式作为初始化程序。
对象声明中使用的
constexpr
说明符将对象声明为const
。这样的对象应具有文字类型并应初始化。如果它是由构造函数调用初始化的,那么该调用应该是一个常量表达式。否则,或者如果在引用声明中使用constexpr
说明符,则其初始值设定项中出现的每个完整表达式都应为常量表达式。 [注意:用于转换初始化表达式的每个隐式转换和用于初始化的每个构造函数调用都是这种完整表达式的一部分。 - 结束记录]