c++的左值(lvalue),右值(rvalue),移动语义(move),完美转发(forward)c++的左值,右值 精辟总结 当一个对象被用作右值的时候,使用的是对象的值(内容);当对象被用作左值的时候,用的是对象的身份(在内存中的位置)左值右值,完美转发参考文档。
左值持久,右值短暂;move:显示地将一个左值转换为对应右值的引用类型,还可以获取绑定到左值上的右值引用,int&& rr3 = std::move(rrl); 使用move就意味着除了对rrl赋值或销毁它外,我们不再使用它。 std::forward()与std::move()相区别的是,move()会无条件的将一个参数转换成右值,而forward()则会保留参数的左右值类型,可以使用std::forward实现完美转发。 移动语义解决了无用拷贝的问题:移动构造函数; 右值引用:函数的返回值。 int& 左值引用 int&& 右值引用 c++中无用拷贝的情况
class Test {
public:
string desc;
int * arr{nullptr};
Test():arr(new int[5000]{1,2,3,4}) {
cout << "default constructor" << endl;
}
Test(const Test & t) {
cout << "copy constructor" << endl;
if (arr == nullptr) arr = new int[5000];
copy(t.arr,t.arr+5000, arr);
}
~Test(){
cout << "destructor " << desc << endl;
delete [] arr;
}
};
Test createTest() {
return Test();
}
int main(){
Test reusable;
reusable.desc = "reusable";
Test duplicated(reusable);
duplicated.desc = "duplicated";
Test t(createTest());
t.desc = "t";
cout<<"end"<<endl;
}
运行结果 default constructor
copy constructor
default constructor
end
destructor t
destructor duplicated
destructor reusable
使用移动语义避免无用的拷贝
class Test {
public:
string desc;
int * arr{nullptr};
Test():arr(new int[5000]{1,2,3,4}) {
cout << "__default constructor" << endl;
}
Test(const Test & t) {
cout << "__copy constructor" << endl;
if (arr == nullptr) arr = new int[5000];
copy(t.arr,t.arr+5000, arr);
}
Test(Test && t): arr(t.arr) {
cout << "__move constructor" << endl;
t.arr = nullptr;
}
~Test(){
cout << "..destructor " << desc << endl;
delete [] arr;
}
};
Test createTest(string str) {
Test rt;
rt.desc = str;
cout<<"createTest:"<<&rt<<endl;
return rt;
}
void main(){
Test reusable;
reusable.desc = "reusable";
cout<<"reusable.arr "<<reusable.arr<<endl;
Test duplicated(std::move(reusable));
duplicated.desc = "duplicated";
cout<<"reusable.arr "<<reusable.arr<<endl;
cout<<"duplicated.arr "<<duplicated.arr<<endl;
cout<<"rvalue--"<<endl;
Test&& rt1 = createTest("rval");
cout<<"rt1.arr "<<rt1.arr<<endl;
cout<<"no rvalue--"<<endl;
Test rt2 = createTest("normalVal");
cout<<"createTest:"<<&rt2<<endl;
cout<<"rt2.arr "<<rt2.arr<<endl;
cout<<"end"<<endl;
}
输出结果 __default constructor
reusable.arr 0x56521b946e70
__move constructor
reusable.arr 0
duplicated.arr 0x56521b946e70
rvalue--
__default constructor
createTest:0x7ffd092ea390
rt1.arr 0x56521b94c0b0
no rvalue--
__default constructor
createTest:0x7ffd092ea3c0
createTest:0x7ffd092ea3c0
rt2.arr 0x56521b950ee0
end
..destructor normalVal
..destructor rval
..destructor duplicated
..destructor reusable
|