首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >[expr.const]节中的“前初始化”一词的含义是什么?

[expr.const]节中的“前初始化”一词的含义是什么?
EN

Stack Overflow用户
提问于 2020-08-27 06:20:26
回答 2查看 187关注 0票数 5
代码语言:javascript
复制
constexpr int func(int const& rf){
    return rf;
}
int main(){
   constexpr int value = func(0);
}

考虑到上面的代码,变量value应该由一个常量表达式(即func(0) )初始化,该表达式首先是一个核心常量表达式。要确定表达式func(0)是否是核心常量表达式,将对其应用以下规则,即:

expr.const#2.7

表达式e是核心常量表达式,除非e的计算遵循抽象机器的规则计算下列表达式之一: 从lvalue到rvalue的转换,除非应用于 .或 (2.7.4)文字类型的非易失性极值,指在e的评价范围内开始生命周期的非易失性物体;

尽管lvalue-to-rvalue conversion被应用于rf,并且这种转换满足了重点(2.7.4),但是,请看下一段,即:

expr.const#2.11

一个id表达式,它引用引用类型的变量或数据成员,除非引用在初始化之前有一个,并且

  • (2.11.1)它用一个常量表达式初始化,或者,
  • (2.11.2)其寿命始于对e的评价;

我不知道preceding initialization这个词到底是什么意思?它意味着在使用变量之前应该初始化它,还是意味着在变量的声明中应该有一个初始化器。无论如何,在将lvalue-to-rvalue conversion应用于glvalue rf之前,应该对glvalue rf进行评估,以确定对象的标识,该对象由以下方法裁决:

glvalue是一种表达式,其计算值决定对象、位字段或函数的身份.

这意味着不仅要遵守子弹expr.const#2.7,而且要遵守expr.const#2.11。

因为id表达式rf是引用类型的。因此,为了使表达式func(0)成为核心常量表达式,id表达式rf必须在初始化之前有一个,并且至少满足符号(2.11.1)和(2.11.2)中的一个。在我的示例中,rf遵循项目(2.11.2),编译器同意func(0)是一个常量表达式。结果是这里,结果似乎证明了在第一个示例中,preceding initialization意味着be initialized,而不是由于参数声明而具有的初始化器。

为了检查这种想法,我测试了以下代码:

代码语言:javascript
复制
constexpr int func(int const& rf){
    constexpr int const& v = rf;  
    return 0;
}
int main(){
   static int const data = 0;
   constexpr int value = func(data);
}

编译器的结果指出,rf不是一个常量表达式。我对这个结果感到困惑。根据上述假设。rf有一个前面的初始化,并且遵从(2.11.1)符号,因为data是一个常量表达式,即使(2.11.2)不满足。

所以,我想知道preceding initialization这个短语到底是什么意思?如果这意味着变量的声明有一个初始化器,那么第一个示例中的表达式func(0)怎么可能是一个常量表达式?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-08-27 07:23:32

结果似乎表明,“前面的初始化”意味着“被初始化”,而不是由于参数声明而具有的初始化器在第一个示例中没有初始化器。

它确实意味着“被初始化”,但更重要的是,它涉及到正在计算的表达式的上下文中的前一个初始化的可见性。在您的示例中,在计算func(0)的上下文中,编译器具有使用0查看rf初始化的上下文。但是,在计算func中的表达式func时,它没有看到rf的初始化。分析是局部的,因为它不分析每个呼叫站点。这导致表达式rf本身在func 中,而不是是常量表达式,而func(0)是常量表达式。

如果你要写这篇文章的话:

代码语言:javascript
复制
constexpr int func(int const& rf) {
  /* constexpr */ int const& v = rf;
  return v;
}

int main() {
  static int const data = 0;
  constexpr int value = func(data);
}

这也是可以的,因为在func(data)的上下文中,rf使用常量表达式data进行了前面的初始化,而v使用rf进行了前面的初始化--即不是--一个常量表达式,但它的生存期是在func(data)的计算范围内开始的。

票数 6
EN

Stack Overflow用户

发布于 2020-08-27 07:34:09

我是CWG2186

2186.不清楚“前面的初始化”必须在之前 类似于问题2166的关注,8.20 expr.const项目2.7.1的要求是 -整型或枚举类型的非易失性极值,指具有先前初始化的完整非易失性const对象,用常量表达式初始化,或 没有指定确定“前一个初始化”的点:它是在对变量的引用在词汇上出现的点上,还是在发生最外层常量计算的点?在这一点上,在执行方面存在分歧。

但其意义应该是“词汇上的”,因为ODR。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63610256

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档