c++的左值,右值 精辟總結(jié)
成都創(chuàng)新互聯(lián)公司堅(jiān)持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:成都網(wǎng)站制作、做網(wǎng)站、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿足客戶于互聯(lián)網(wǎng)時(shí)代的萬秀網(wǎng)站設(shè)計(jì)、移動(dòng)媒體設(shè)計(jì)的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!
當(dāng)一個(gè)對(duì)象被用作右值的時(shí)候,使用的是對(duì)象的值(內(nèi)容);當(dāng)對(duì)象被用作左值的時(shí)候,用的是對(duì)象的身份(在內(nèi)存中的位置)左值右值,完美轉(zhuǎn)發(fā)參考文檔。
左值持久,右值短暫;move:顯示地將一個(gè)左值轉(zhuǎn)換為對(duì)應(yīng)右值的引用類型,還可以獲取綁定到左值上的右值引用,int&& rr3 = std::move(rrl); 使用move就意味著除了對(duì)rrl賦值或銷毀它外,我們不再使用它。
std::forward
移動(dòng)語義解決了無用拷貝的問題:移動(dòng)構(gòu)造函數(shù);
右值引用:函數(shù)的返回值。
int& 左值引用
int&& 右值引用
/*類里面 沒有移動(dòng)構(gòu)造函數(shù)
這樣就會(huì)使用 copy construct function,會(huì)導(dǎo)致大量無用的 memory copy。
*/
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"<
運(yùn)行結(jié)果
default constructor
copy constructor
default constructor
end
destructor t
destructor duplicated
destructor reusable
/*使用移動(dòng) construct function,避免無用的memory copy。
*/
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]; //在這里要將 t.arr 置為空,因?yàn)榻?jīng)過move之后,我們認(rèn)為不在使用這個(gè)值了,避免在新的對(duì)象中把指針釋放后,原來的對(duì)象中存在野指針的現(xiàn)象
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<
輸出結(jié)果
__default constructor
reusable.arr 0xb946e70
__move constructor
reusable.arr 0
duplicated.arr 0xb946e70
rvalue--
__default constructor
createTest:0x7ffd092ea390
rt1.arr 0xb94c0b0
no rvalue--
__default constructor
createTest:0x7ffd092ea3c0
createTest:0x7ffd092ea3c0
rt2.arr 0xb950ee0
end
..destructor normalVal
..destructor rval
..destructor duplicated
..destructor reusable
//左值引用和右值引用
void foo(const int & i) { cout << "const int & " << i << endl; }
void foo(int & i) { cout << "int & " << i << endl; }
void foo(int && i) { cout << "int && " << i << endl; }
void foo(const int && i) { cout << "const int && " << i << endl; }
void main(){
int i = 2;
foo(i);
foo(2);
foo([]()->const int && {return 2;}());
}
/*在main當(dāng)中調(diào)用relay,Test的臨時(shí)對(duì)象作為一個(gè)右值傳入relay,在relay當(dāng)中又被轉(zhuǎn)發(fā)給了func,那這時(shí)候轉(zhuǎn)發(fā)
給func的參數(shù)t也應(yīng)當(dāng)是一個(gè)右值。也就是說,我們希望:當(dāng)relay的參數(shù)是右值的時(shí)候,func的參數(shù)也是右值;當(dāng)
relay的參數(shù)是左值的時(shí)候,func的參數(shù)也是左值。
*/
class Test {
public:
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" << endl;
delete [] arr;
}
};
template
void func(T t) {
cout << "in func" << endl;
}
template
void relay(T&& t) {
cout << "in relay" << endl;
func(t);
}
//完美轉(zhuǎn)發(fā)
template
void relay1(T&& t) {
cout << "in relay " << endl;
func(std::forward(t));
}
void main() {
// relay(Test());
// cout<<"end"<
更多編程資料見公眾號(hào) xutopia77