溫馨提示×

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

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

C++中的臨時(shí)對(duì)象舉例分析

發(fā)布時(shí)間:2021-11-24 10:29:25 來源:億速云 閱讀:173 作者:iii 欄目:互聯(lián)網(wǎng)科技

本篇內(nèi)容主要講解“C++中的臨時(shí)對(duì)象舉例分析”,感興趣的朋友不妨來看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“C++中的臨時(shí)對(duì)象舉例分析”吧!

一、以值的方式給函數(shù)傳參
1、按值傳遞
按值傳遞時(shí),首先將需要傳給函數(shù)的參數(shù),調(diào)用拷貝構(gòu)造函數(shù)創(chuàng)建一個(gè)副本,所有在函數(shù)里的操作都是針對(duì)這個(gè)副本,也正是因?yàn)檫@個(gè)原因,在函數(shù)體力對(duì)該副本進(jìn)行任何操作都不會(huì)影響原參數(shù)。
2、按引用傳遞
引用則不然,它是對(duì)象本身,只是一個(gè)別名而已??梢詤⒖贾羔樅鸵檬裁磿r(shí)候用?來理解引用。
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;
}

運(yùn)行結(jié)果:
這里寫圖片描述
通過以上程序可以看到調(diào)用了拷貝構(gòu)造函數(shù),這是tm在傳給GetSum函數(shù)做參數(shù)時(shí)調(diào)用的。此時(shí)調(diào)用拷貝構(gòu)造函數(shù)創(chuàng)建了一個(gè)副本,為GetSum函數(shù)體內(nèi)使用。通過運(yùn)行結(jié)果可以看到,在GetSum函數(shù)體內(nèi)對(duì)tm副本進(jìn)行的修改并沒有影響到tm本身。

可以按照如下方式修改,函數(shù)聲明和定義都需要改:

int GetSum(TempObj& ts);
int TempObj::GetSum(TempObj& ts)
{
    int tmp = ts.m_Number + ts.m_Size;
    ts.m_Number = 1000;//此時(shí)通過ts這個(gè)引用對(duì)象本身
    return tmp;
}

運(yùn)行結(jié)果:
這里寫圖片描述
通過傳遞常量引用,減少了一次臨時(shí)對(duì)象的創(chuàng)建。這個(gè)改動(dòng)也許很小,但對(duì)多繼承的對(duì)象來說在構(gòu)建時(shí)要遞歸調(diào)用所有基類的構(gòu)造函數(shù),這對(duì)于性能來說是個(gè)很大的消耗。

二、類型轉(zhuǎn)換生成的臨時(shí)對(duì)象

#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;
}

運(yùn)行結(jié)果:
這里寫圖片描述
main函數(shù)創(chuàng)建了兩個(gè)對(duì)象,但輸出卻調(diào)用了三次構(gòu)造函數(shù)。關(guān)鍵在sum = 1000;本身1000和sum類型不符,但編譯器為了通過編譯以1000為參數(shù)調(diào)用構(gòu)造函數(shù)創(chuàng)建了一個(gè)臨時(shí)對(duì)象。

解決辦法:

void main()
{
    TempObj tm(10,20);
    TempObj sum = 1000;
    cout << "sum=" << tm.GetSum(sum) << endl;
}

輸出結(jié)果:
這里寫圖片描述
此時(shí),“=”號(hào)由原本的賦值變成了構(gòu)造。對(duì)sum的構(gòu)造推遲了,當(dāng)定義TempObj sum時(shí),在main的棧中為sum對(duì)象創(chuàng)建了一個(gè)預(yù)留空間,而我們用1000調(diào)用構(gòu)造函數(shù)時(shí),此時(shí)的構(gòu)造函數(shù)是在sum預(yù)留的空間中進(jìn)行的,因此減少了一次臨時(shí)對(duì)象的創(chuàng)建。

三、函數(shù)返回一個(gè)對(duì)象
當(dāng)函數(shù)需要返回一個(gè)對(duì)象,它會(huì)在棧中創(chuàng)建一個(gè)臨時(shí)對(duì)象,存儲(chǔ)函數(shù)的返回值。

#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;
}

運(yùn)行結(jié)果:
這里寫圖片描述
分析:
上述代碼sum = Double(tm);這條語句生成了兩個(gè)對(duì)象。第一,顯示創(chuàng)建了一個(gè)tmp臨時(shí)對(duì)象(TempObj tmp;);其次,將temp對(duì)象返回,返回過程中調(diào)用了拷貝構(gòu)造函數(shù)創(chuàng)建一個(gè)返回對(duì)象(return tmp;);第三,將返回結(jié)果通過調(diào)用賦值運(yùn)算符重載函數(shù)賦值給sum(sum = Double(tm);),該步驟沒有創(chuàng)建對(duì)象。可參考C++賦值運(yùn)算符重載函數(shù)和拷貝構(gòu)造函數(shù)進(jìn)行理解。
注意,第二步創(chuàng)建的返回對(duì)象是難以避免的,此處如果是返回引用,在函數(shù)里創(chuàng)建的局部對(duì)象,在返回時(shí)就被銷毀了,這時(shí)若再引用該對(duì)象就會(huì)產(chǎn)生未知錯(cuò)誤。

可以直接操作返回對(duì)象,具體如下:

TempObj Double(TempObj& to)
{
    return to.m_Number*2;
}

也可以結(jié)合上面講到的類型轉(zhuǎn)換生成臨時(shí)對(duì)象解決辦法進(jìn)行優(yōu)化,具體修改如下:

#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;
}

運(yùn)行結(jié)果如下:
這里寫圖片描述

分析發(fā)現(xiàn)減少了一次構(gòu)造函數(shù)調(diào)用tmp,一次拷貝構(gòu)造函數(shù)(tmp拷貝給返回對(duì)象)調(diào)用和一次賦值運(yùn)算符重載函數(shù)調(diào)用。這是因?yàn)榉祷貙?duì)象直接使用編譯器為sum預(yù)留的空間,所以減少了返回臨時(shí)對(duì)象的生成,返回對(duì)象即是sum,返回對(duì)象的創(chuàng)建即是sum對(duì)象的創(chuàng)建。

到此,相信大家對(duì)“C++中的臨時(shí)對(duì)象舉例分析”有了更深的了解,不妨來實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

c++
AI