当前位置: 首页 > 知识库问答 >
问题:

当其参数是对文字类型的引用时的常量函数

高德水
2023-03-14
constexpr int func(int const& rf){
   return rf;
}
int main(){
  constexpr int value = func(0);
}

考虑上面的代码,它会被编译并且格式良好,但是我对此感到困惑。根据[[stmt.return#2]]

return语句通过从操作数复制初始化来初始化(显式或隐式)函数调用的glvalue result或prvalue result对象。

所以,我认为返回语句相当于以下内容:

constexpr void func(int const& rf){
   constexpr int value = rf;  //#1
}
int main(){
   func(0);
}

然而,这一次,代码的格式不正确。因为它受这些规则的约束:

引用引用类型的变量或数据成员的id表达式,除非引用具有先前的初始化并且

  • 它用常量表达式或
  • 它的寿命开始于对e的评估

rf没有前面的初始化,它的生命周期在进入函数体之前就开始了,因此,当在#1处评估rf时,它的生命周期不会在此表达式的评估范围内开始。所以,表达式不是常量表达式,但是,作为等价形式,我想知道为什么当对象value从操作数rf复制初始化时,第一个代码格式良好?

我认为这些问题相当于这个表格:

constexpr int func(){
    int result = 0;
    return result;
}

int main()
{
    constexpr int x = func();
}

当对return语句的操作数result应用左值到右值的转换时,它将违反以下规则:

左值到右值的转换,除非应用于

  • 整数或枚举类型的非易失性glvalue,它引用具有先前初始化的完整非易失性const对象,使用常量表达式初始化

result是用常量表达式而不是常量对象初始化的,因此它违反了此规则,将不是常量表达式。为什么它的形式很好?为什么constexpr函数可以返回非常量变量?到目前为止,我还没有找到任何额外的规则允许这样做。

共有1个答案

阎劲
2023-03-14

所以,我认为return语句相当于

如果等效是指如果它有效,它将是复制初始化,那么是的。但是它是无效的,所以称之为等效是不正确的。

然而,作为等价形式,我想知道,当对象值copy从html" target="_blank">操作数rf初始化时,为什么第一个代码格式良好?

因为复制初始化在这里并不重要。原因是

constexpr int value = func(0);

有效,而

constexpr int value = rf;

不是,完全是由于初始化中使用的表达式的属性。复制初始化不会取消第二个或允许第一个的资格。

对于第一个示例,func(0)是必须满足常量表达式要求的表达式。它是一个生成prvalue的表达式。该prvalue最终是从某个引用复制初始化的。然而,该引用指的是仅在常量求值期间存在的某个对象。即在调用函数之前为保存0而创建的“临时”。这就是为什么prvalue结果可以常量求值,然后用于初始化constexr变量。

在第二个示例中,另一方面,rf在常量表达式中不可用。你引用的那一段constepr函数仍然是常规函数,也可在“运行时”调用。此外,编译器不必不断折叠它们。因此,无论何时求值,它们都必须是有效函数。因此,由于无论函数如何调用,rf在常量表达式中都不可用,因此它不能用于初始化必须由函数本身内的常量表达式无条件初始化的内容。

把它放在standardese的框架中,初始化的完整表达式可以访问在其中创建的对象。在

constexpr int value = func(0);

rf绑定到作为完整表达式的一部分而存在的对象。所以我们可以访问它。但是,在

constexpr int value = rf;

rf未绑定到以该完整表达式开始的整个生命周期中的对象。

每个变量声明都是它自己的自包含“上下文”,用于检查常量表达式的有效性。在这方面,它们是不相交的。

result是用常量表达式而不是常量对象初始化的,因此它违反了这个规则

它违反了该项目符号,但该子句中有几个项目符号是有效的左值到右值转换的替代项。它与

左值到右值的转换,除非应用于

  • 文本类型的非易失性glvalue,指的是一个非易失性对象,其生存期在e的计算范围内开始

result是一种文本类型,在对func()求值期间,它开始生效(以及退出)。因此,它的形式是合理的。

 类似资料:
  • 问题内容: 我正在建立一个很小的MySQL数据库,该数据库存储名字,姓氏,电子邮件和电话号码,并且正在努力寻找每个字段的“完美”数据类型。我知道没有一个完美的答案,但是对于诸如此类的常用字段必须有某种通用约定。例如,我确定未格式化的美国电话号码太大,无法存储为未签名的int,它必须至少是bigint。 因为我确信其他人可能会觉得这很有用,所以我不想将我的问题仅局限于上面提到的领域。 哪些数据类型适

  • 问题内容: 我有以下课程(来自简单的Spring教程) 其中Validator类是Spring 2.5中的类。 如果我尝试向其中添加参数,则supports方法显示警告(Class是原始类型。对泛型类型Class的引用应进行参数化) 我收到以下错误: 关于这种类型的问题有很多线索,但是我想获得一个完整的答案并真正理解它,而不会用“隐藏”这个问题! 问题答案: 接口使用原始类型声明该方法。在这种情况

  • 其它类简介: 该文档正在编写中...

  • 问题内容: 我之前在程序中有这些确切的代码行,但没有收到此错误。我做了一些搜索,发现的结果使我有些头疼。有任何想法吗? 错误是: 问题答案: 您可以使用: 发生这种情况是因为现在是泛型类。

  • 问题内容: 我对Eclipse Galileo有一个奇怪的问题。 我将Java 1.6设置为我的JRE。在这行代码上 我在Eclipse的问题列表中看到以下错误: Collection类型不是通用的;不能使用参数对其进行参数化 我用Ant构建这个项目没有任何问题。 我该如何解决?看起来这是Eclipse问题,但是由于这个错误,我无法从IDE编译/发布项目。 问题答案: 对于那些从Google那里可