如果引用由函数返回,则使auto成为引用

时间:2018-11-24 17:09:56

标签: c++ reference language-lawyer type-inference auto

我需要以下代码才能工作:

class Parent{
public:
     virtual void fun(){throw 0};

};

class Child:public Parent{
public:
     virtual void fun(){/*Success*/};

};
Parent& getChild(){
     return *(new Child());
}

void main(){
    auto child=getChild();
    child.fun();    
}

但是由于某种原因,auto会创建Parent而不是Parent &,这会正确使用派生的方法。有没有一种方法可以强制auto创建引用而不是使用简单的实例?

1 个答案:

答案 0 :(得分:0)

C ++标准说明从初始化值中扣除auto:

  

声明[dcl.spec.auto]/1: autodecltype(auto)   类型说明符用于指定占位符类型   以后由从初始值设定项中推导得出。

     

初始化程序[dcl.init]/1:声明程序可以指定初始值   值(用于声明的标识符)。

因此,当您编写以下声明符时:

int t = f(10); 
auto x = y; 
auto child = getChild(); 

右边被评估为表达式,该表达式产生一个值。并且此值用于初始化在左侧声明的变量。

值不是参考。它不像指针和地址。在表达式评估中,每当使用引用时,都要考虑引用值。您可以通过以下简单的代码段看到它:

int x=15;
int&y = x; 
cout << x <<", " << y <<", " << &x<<endl;
cout << typeid(x).name() <<", " << typeid(y).name() <<", " << typeid(&x).name() <<endl; 

在您的情况下,表达式值因此是Parent而不是Parent &。这就是为什么您的auto被推导为Parent类型的原因。

但是,C ++标准并未以相同方式考虑所有值。在[basic.lval]中,它对不同类型的值(可以是 lvalues xvalues prvalues )进行了重要区分。在您的情况下,getChild()得出的左值是您引用的对象,而不是它的某些临时副本。

具有这样的左值时,可以创建对其的引用:

  

[dcl.ref] / 2:使用&声明的引用类型称为   左值引用,(...)

但是您需要明确地做到这一点,说您的汽车应该是一个参考:

auto &child = getChild();

编辑: 有关自动工作方式的更多信息:Herb Sutter's GotW blog