中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

C++中的臨時對象舉例分析

發布時間:2021-11-24 10:29:25 來源:億速云 閱讀:174 作者:iii 欄目:互聯網科技

本篇內容主要講解“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++中的臨時對象舉例分析”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

c++
AI

大庆市| 莒南县| 大悟县| 乌鲁木齐市| 鞍山市| 石狮市| 朝阳区| 兴山县| 英吉沙县| 惠州市| 青铜峡市| 泸州市| 杭锦后旗| 霞浦县| 三台县| 靖边县| 三河市| 新丰县| 城口县| 临夏县| 周至县| 峨边| 阜南县| 铜陵市| 唐山市| 全南县| 勃利县| 田东县| 洛扎县| 鹤山市| 武冈市| 会泽县| 鄢陵县| 久治县| 清远市| 鹤庆县| 平塘县| 乳山市| 新乡县| 北宁市| 济南市|