首页 > 解决方案 > 返回类型为引用时的规则是什么

问题描述

#include <iostream>
int func0(){
  int a = 0;
  return a;
}
int&& func1(){
   int a = 0;
   return a;
}
int main(){
  int&& result0 = func0();
  int&& result1 = func1();
}

return statement规则是:

  1. 函数通过 return 语句返回给它的调用者。
  2. [...] return 语句通过操作数的复制初始化来初始化(显式或隐式)函数调用的glvalue 结果或 prvalue 结果对象

关于如何初始化函数调用的对象的规则只有#2。

我们知道表达式func0()是纯右值。引用result0需要绑定一个对象,所以temporary materialization conversion要把prvalue转换成一个xvalue,所以临时对象作为prvalue结果对象从 的操作数初始化return,然后引用reusult0绑定到临时对象。

但是我们知道result1是一个引用并且返回类型func1也是引用。对于这种情况,[stmt.return]并没有明确涵盖这种情况,因为result1是引用而不是object(既不是 glvalue reuslt 对象也不是 prvalue 结果对象),那么这种情况的规则是什么?如果我错过了什么,请纠正我。

标签: c++returnc++17language-lawyer

解决方案


你的分析result0是正确的。

但本案没有临时实现result1。“glvalue 结果”是通过从操作数a复制初始化来初始化的引用,并且对相同类型的引用的复制初始化意味着引用直接绑定(dcl.init.ref/5,通过 dcl.init/17.2) . 然后result1绑定到 glvalue 结果。

这会创建一个悬空引用;声明return从生命周期扩展规则中明确排除(class.temporary/6.2)。

在这种情况下int result2 = func1();,glvalue 结果(引用)使用 result object 进行左值到右值的转换result2,这会导致未定义的行为,因为 glvalue 结果是悬空的。


推荐阅读