C ++右值转发

时间:2017-03-18 09:42:22

标签: c++ move-semantics rvalue-reference

据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. 我的cheaty构造函数的添加如何改变任何东西,它是否符合标准?
  3. 如果这些都不是有效的(这是我所担心的),我怎么能创建cheaty构造函数2.0,让我传递非const rvalue? [请不要模板化perferct转发,我想完全保留我的源代码.cpp]所有IDat都有有效的移动构造函数和赋值运算符

1 个答案:

答案 0 :(得分:0)

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

归结为以下事实:

  • Rvalue引用会延长它们持有的对象的生命周期,直到它们超出范围
  • Const Lvalue引用也是如此,但显然无法修改
  • 非const Lvalue使用rvalue ref初始化的引用 NOT 延长rvalue的生命周期
  • 由于引用折叠,委托构造函数调用左值构造函数,而不是自身

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

Here (especially the paragraph entitled Rvalue references is very good)https://pbs.twimg.com/profile_images/450103729383956480/Tiys3m4x.jpeg

这就是为什么

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
    }