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
}
}
现在我的问题是:
- 第一个真的是不符合标准的 c++ 吗?
- 添加我作弊的构造函数有何改变,是否符合标准?
- 如果这些都无效(这是我担心的),我怎么能创建作弊的构造函数 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
}
根据 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
}
}
现在我的问题是:
- 第一个真的是不符合标准的 c++ 吗?
- 添加我作弊的构造函数有何改变,是否符合标准?
- 如果这些都无效(这是我担心的),我怎么能创建作弊的构造函数 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
}