C++ 右值转发

C++ rvalue forwarding

根据 Resharper 的说法,这里是无效的 c++:

class IData{
    IData();
    virtual doStuff() = 0;
}
class MyData: public IData{
    MyData(MyData&& mdrv);
    doStuff() override{/*....*/};
}
class DataUser(){
    DataUser(IData& d){   //all explicits are ommitted for brevity, don't call me out on that please :)
        d.doStuff();
    }
}
int main(){
    DataUser d(MyData()); //it complains here: Binding Rvalue Reference to lvalue Reference is a non standard MSVC extension
}

我不能使 IData& const,因为 doStuff 做事(呃!)

我做的是这样的:

 class DataUser(){
     DataUser(IData& d){
         d.doStuff();
     }
     DataUser(IData&& d): DataUser(d){  //added this, no complains anywhere
     }
 }

现在我的问题是:

  1. 第一个真的是不符合标准的 c++ 吗?
  2. 添加我作弊的构造函数有何改变,是否符合标准?
  3. 如果这些都无效(这是我担心的),我怎么能创建作弊的构造函数 2.0,让我传递一个 non const 右值? [请不要模板化完美转发,我想将我的源代码完全保留在 .cpp 中]所有 IData 都有有效的移动构造函数和赋值运算符

由于@Incomputable 的惊人帮助,我能够解决这个问题。

归结为以下事实:

  • 右值引用延长了它们持有的对象的生命周期,直到它们超出范围
  • Const Lvalue References 做同样的事情,但显然不能被修改
  • 非 const 使用右值引用初始化的左值引用 NOT 延长右值
  • 的生命周期
  • 由于引用崩溃,委托构造函数调用左值构造函数,而不是它自己

可以找到其他资源(由@Incomputable 再次提供)

Here and Here (especially the paragraph entitled Rvalue references is very good)

这就是为什么

class DataUser(){
    DataUser(IData& d){ 
        d.doStuff();
    }
}
int main(){
    DataUser d(MyData()); //lvalue ref is initalized  with rvalue, Rvalue goes out of scope --> UB
}

但是

class DataUser(){
        DataUser(IData& d){ 
            d.doStuff();
        }
        DataUser(IData&& d): DataUser(d){ //the rvalues lifetime is extended until the constructor exits and d goes out of scope
        }
    }
    int main(){
        DataUser d(MyData()); //this works like a charm and is perfectly legal
    }