您好,登錄后才能下訂單哦!
本篇內容主要講解“C++中的臨時對象舉例分析”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“C++中的臨時對象舉例分析”吧!
一、以值的方式給函數傳參
1、按值傳遞
按值傳遞時,首先將需要傳給函數的參數,調用拷貝構造函數創建一個副本,所有在函數里的操作都是針對這個副本,也正是因為這個原因,在函數體力對該副本進行任何操作都不會影響原參數。
2、按引用傳遞
引用則不然,它是對象本身,只是一個別名而已。可以參考指針和引用什么時候用?來理解引用。
3、例子
#include <iostream>
using namespace std;
class TempObj {
public:
TempObj(int m = 0, int n = 0);
TempObj(TempObj& to)
{
cout << "Copy Constructor" << endl;
m_Number = to.m_Number;
m_Size = to.m_Size;
}
~TempObj()
{
cout << "Deconstructor" << endl;
}
int GetSum(TempObj ts);
public:
int m_Number;
int m_Size;
};
TempObj::TempObj(int m,int n)
{
cout << "Default constructor" << endl;
m_Number = m;
m_Size = n;
cout << "m_Number=" << m_Number <<" "<< "m_Size=" << m_Size << endl;
}
int TempObj::GetSum(TempObj ts)
{
int tmp = ts.m_Number + ts.m_Size;
ts.m_Number = 1000;
return tmp;
}
void main()
{
TempObj tm(10,20);
cout << "sum=" << tm.GetSum(tm) << endl;
cout << "tm.m_Number=" << tm.m_Number << endl;
}
運行結果:
這里寫圖片描述
通過以上程序可以看到調用了拷貝構造函數,這是tm在傳給GetSum函數做參數時調用的。此時調用拷貝構造函數創建了一個副本,為GetSum函數體內使用。通過運行結果可以看到,在GetSum函數體內對tm副本進行的修改并沒有影響到tm本身。
可以按照如下方式修改,函數聲明和定義都需要改:
int GetSum(TempObj& ts);
int TempObj::GetSum(TempObj& ts)
{
int tmp = ts.m_Number + ts.m_Size;
ts.m_Number = 1000;//此時通過ts這個引用對象本身
return tmp;
}
運行結果:
這里寫圖片描述
通過傳遞常量引用,減少了一次臨時對象的創建。這個改動也許很小,但對多繼承的對象來說在構建時要遞歸調用所有基類的構造函數,這對于性能來說是個很大的消耗。
二、類型轉換生成的臨時對象
#include <iostream>
using namespace std;
class TempObj {
public:
TempObj(int m = 0, int n = 0);
TempObj(TempObj& to)
{
cout << "Copy Constructor" << endl;
m_Number = to.m_Number;
m_Size = to.m_Size;
}
~TempObj()
{
//cout << "Deconstructor" << endl;
}
int GetSum(TempObj &ts);
public:
int m_Number;
int m_Size;
};
TempObj::TempObj(int m,int n)
{
cout << "Default constructor" << endl;
m_Number = m;
m_Size = n;
cout << "m_Number=" << m_Number <<" "<< "m_Size=" << m_Size << endl;
}
int TempObj::GetSum(TempObj &ts)
{
int tmp = ts.m_Number + ts.m_Size;
ts.m_Number = 1000;
return tmp;
}
void main()
{
TempObj tm(10,20),sum;
sum = 1000;
cout << "sum=" << tm.GetSum(sum) << endl;
}
運行結果:
這里寫圖片描述
main函數創建了兩個對象,但輸出卻調用了三次構造函數。關鍵在sum = 1000;本身1000和sum類型不符,但編譯器為了通過編譯以1000為參數調用構造函數創建了一個臨時對象。
解決辦法:
void main()
{
TempObj tm(10,20);
TempObj sum = 1000;
cout << "sum=" << tm.GetSum(sum) << endl;
}
輸出結果:
這里寫圖片描述
此時,“=”號由原本的賦值變成了構造。對sum的構造推遲了,當定義TempObj sum時,在main的棧中為sum對象創建了一個預留空間,而我們用1000調用構造函數時,此時的構造函數是在sum預留的空間中進行的,因此減少了一次臨時對象的創建。
三、函數返回一個對象
當函數需要返回一個對象,它會在棧中創建一個臨時對象,存儲函數的返回值。
#include <iostream>
using namespace std;
class TempObj {
public:
TempObj(int m = 0);//default constructor
TempObj(TempObj& to)
{
cout << "copy constructor" << endl;
m_Number = to.m_Number;
}
TempObj& operator=(TempObj& to)
{
cout << "operator=(TempObj& to)" << endl;
m_Number = to.m_Number;
return *this;
}
~TempObj()
{
}
public:
int m_Number;
};
TempObj::TempObj(int m)
{
cout << "default constructor" << endl;
m_Number = m;
cout << "m_Number=" << m_Number << endl;
}
TempObj Double(TempObj& to)
{
TempObj tmp;
tmp.m_Number = to.m_Number*2;
return tmp;
}
void main()
{
TempObj tm(10), sum;
cout << endl;
sum = Double(tm);
cout << endl;
cout << "sum.m_Number=" << sum.m_Number << endl;
}
運行結果:
這里寫圖片描述
分析:
上述代碼sum = Double(tm);這條語句生成了兩個對象。第一,顯示創建了一個tmp臨時對象(TempObj tmp;);其次,將temp對象返回,返回過程中調用了拷貝構造函數創建一個返回對象(return tmp;);第三,將返回結果通過調用賦值運算符重載函數賦值給sum(sum = Double(tm);),該步驟沒有創建對象。可參考C++賦值運算符重載函數和拷貝構造函數進行理解。
注意,第二步創建的返回對象是難以避免的,此處如果是返回引用,在函數里創建的局部對象,在返回時就被銷毀了,這時若再引用該對象就會產生未知錯誤。
可以直接操作返回對象,具體如下:
TempObj Double(TempObj& to)
{
return to.m_Number*2;
}
也可以結合上面講到的類型轉換生成臨時對象解決辦法進行優化,具體修改如下:
#include <iostream>
using namespace std;
class TempObj {
public:
TempObj(int m = 0);//default constructor
TempObj(TempObj& to)
{
cout << "copy constructor" << endl;
m_Number = to.m_Number;
}
TempObj& operator=(TempObj& to)
{
cout << "operator=(TempObj& to)" << endl;
m_Number = to.m_Number;
return *this;
}
~TempObj()
{
}
public:
int m_Number;
};
TempObj::TempObj(int m)
{
cout << "default constructor" << endl;
m_Number = m;
cout << "m_Number=" << m_Number << endl;
}
TempObj Double(TempObj& to)
{
return to.m_Number*2;
}
void main()
{
TempObj tm(10);
cout << endl;
TempObj sum = Double(tm);
cout << endl;
cout << "sum.m_Number=" << sum.m_Number << endl;
}
運行結果如下:
這里寫圖片描述
分析發現減少了一次構造函數調用tmp,一次拷貝構造函數(tmp拷貝給返回對象)調用和一次賦值運算符重載函數調用。這是因為返回對象直接使用編譯器為sum預留的空間,所以減少了返回臨時對象的生成,返回對象即是sum,返回對象的創建即是sum對象的創建。
到此,相信大家對“C++中的臨時對象舉例分析”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。