亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

解析C++中臨時(shí)對(duì)象的產(chǎn)生情況

 更新時(shí)間:2023年06月19日 11:01:54   作者:Allen.Su  
臨時(shí)對(duì)象的產(chǎn)生和銷毀都是有成本的,都會(huì)影響程序的執(zhí)行性能和效率,所以如果能了解臨時(shí)對(duì)象產(chǎn)生的原因,就可以提升程序的性能和效率,下面小編就來和大家聊聊臨時(shí)對(duì)象產(chǎn)生的幾種情況吧

有些臨時(shí)對(duì)象是系統(tǒng)自己產(chǎn)生的,又有一些臨時(shí)對(duì)象卻是因?yàn)榇a的書寫問題而產(chǎn)生的,因?yàn)榕R時(shí)對(duì)象會(huì)額外消耗系統(tǒng)資源,所以編寫代碼的原則就是產(chǎn)生的臨時(shí)對(duì)象越少越好。臨時(shí)對(duì)象一般都是在棧上,所以一般都不會(huì)手動(dòng)去釋放。

為什么要了解臨時(shí)對(duì)象?因?yàn)榕R時(shí)對(duì)象的產(chǎn)生和銷毀都是有成本的,都會(huì)影響程序的執(zhí)行性能和效率,所以如果能有效地減少臨時(shí)對(duì)象的產(chǎn)生,那么無疑意味著程序性能和效率的提升。

一、產(chǎn)生臨時(shí)對(duì)象的情況

1.1 以值的方式給函數(shù)傳遞參數(shù) - 如何優(yōu)化呢

先看如下案例:

class CTempValue
{
public:
    int val1;
    int val2;
public:
    //構(gòu)造函數(shù)
    CTempValue(int v1 = 0, int v2 = 0)
    {
        cout << "調(diào)用構(gòu)造函數(shù)" << endl;
        val1 = v1;
        val2 = v2;
        cout << "val1 = " << val1 << endl;
        cout << "val2 = " << val2 << endl;
    }
    ~CTempValue()
    {
        cout << "調(diào)用了析構(gòu)函數(shù)" << endl;
    }
    //拷貝構(gòu)造函數(shù)
    CTempValue(const CTempValue& t)
    {
        cout << "調(diào)用拷貝構(gòu)造函數(shù)" << endl;
        val1 = t.val1;
        val2 = t.val2;
        cout << "val1 = " << val1 << endl;
        cout << "val2 = " << val2 << endl;
    }
    int Add(CTempValue tobj)
    {
        int tmp = tobj.val1 + tobj.val2;
        tobj.val1 = 1000;   //這里的修改對(duì)外界沒有影響
        return tmp;
    }
};
???????int main()
{
    CTempValue tm(10, 20);  //調(diào)用構(gòu)造函數(shù)
    int Sum = tm.Add(tm);   // 這會(huì)調(diào)用拷貝構(gòu)造函數(shù)的執(zhí)行
    cout << "Sum = " << Sum << endl;  //Sum = 30
    cout << "tm.val1 = " << tm.val1 << endl; //tm.val1 = 10
    return 0;
}

運(yùn)行結(jié)果如下:

調(diào)用構(gòu)造函數(shù)
調(diào)用拷貝構(gòu)造函數(shù)
調(diào)用了析構(gòu)函數(shù)
Sum = 30
tm.val1 = 10
調(diào)用了析構(gòu)函數(shù)

請(qǐng)注意,結(jié)果中調(diào)用了拷貝構(gòu)造函數(shù),為什么調(diào)用CTempValue類的拷貝構(gòu)造函數(shù)呢?

這是因?yàn)檎{(diào)用Add成員函數(shù)時(shí)把對(duì)象tm傳遞給了Add成員函數(shù),此時(shí),系統(tǒng)會(huì)調(diào)用拷貝構(gòu)造函數(shù)創(chuàng)建一個(gè)副本tobj(成員函數(shù)Add的形參),用于在函數(shù)體Add內(nèi)使用,因?yàn)閠m對(duì)象的vall值(tm對(duì)象的vall值仍舊為10)。

形參tobj是一個(gè)局部對(duì)象(局部變量),從程序功能的角度來講,函數(shù)體內(nèi)需要臨時(shí)使用它一下,來完成一個(gè)程序上的一個(gè)功能,它確實(shí)是一個(gè)局部變量,只能在Add函數(shù)體里使用。所以嚴(yán)格意義來講,它又不能稱為一個(gè)真正意義的臨時(shí)對(duì)象,因?yàn)檎嬲呐R時(shí)對(duì)象往往指的是真實(shí)存在,但又感覺不到的對(duì)象(至少從代碼上不能直接看到的對(duì)象)。

但是,對(duì)于目前確實(shí)生成了tobj對(duì)象,并且調(diào)用了類的拷貝構(gòu)造函數(shù),有了復(fù)制的動(dòng)作,就會(huì)影響程序的執(zhí)行效率。

那如何優(yōu)化呢?

我們可以使用引用:

int Add(CTempValue& tobj){}

1.2 類型轉(zhuǎn)換生成的臨時(shí)對(duì)象 - 如何優(yōu)化呢

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

接下來,我們看下真正意義的臨時(shí)對(duì)象,因?yàn)檫@個(gè)臨時(shí)對(duì)象確實(shí)存在,但是從程序代碼的角度不能直接看到它。

CTempValue sum;
sum = 1000;

執(zhí)行一下,程序結(jié)果如下:

調(diào)用構(gòu)造函數(shù)
val1 = 0
val2 = 0
調(diào)用構(gòu)造函數(shù)
val1 = 1000
val2 = 0
調(diào)用了析構(gòu)函數(shù)
調(diào)用了析構(gòu)函數(shù)

在執(zhí)行sum = 1000;系統(tǒng)調(diào)用了一次CTempValue類的構(gòu)造函數(shù)和析構(gòu)函數(shù),這說明系統(tǒng)肯定產(chǎn)生了一個(gè)對(duì)象,但這個(gè)對(duì)象在哪里,通過代碼完全看不到,所以這個(gè)對(duì)象是一個(gè)真正的臨時(shí)對(duì)象。

那么,產(chǎn)生這個(gè)臨時(shí)對(duì)象的原因是什么呢?

是因?yàn)榘?000賦給sum,而sum本身是一個(gè)CTempValue類型的對(duì)象,1000是一個(gè)數(shù)字,那怎么把數(shù)字能轉(zhuǎn)化成CTempValue類型的對(duì)象呢?所以編譯器這里幫助我們以1000為參數(shù)調(diào)用了CTempValue的構(gòu)造函數(shù)創(chuàng)建了一個(gè)臨時(shí)對(duì)象,因?yàn)镃TempValue構(gòu)造函數(shù)的兩個(gè)參數(shù)都有默認(rèn)值,所以這里的數(shù)字1000就頂替了第一個(gè)參數(shù),而第二個(gè)參數(shù)系統(tǒng)就用了默認(rèn)值,所以從1000是可以成功創(chuàng)建出CTempValue對(duì)象的。

為了進(jìn)一步觀察,增加拷貝賦值運(yùn)算符的代碼:

CTempValue& operator=(const CTempValue& tmpv)
{
    cout << "調(diào)用了拷貝賦值運(yùn)算符" << endl;
    val1 = tmpv.val1;
    val2 = tmpv.val2;
    cout << "val1 = " << val1 << endl;
    cout << "val2 = " << val2 << endl;
    return *this;
}

執(zhí)行程序,看下結(jié)果:

調(diào)用構(gòu)造函數(shù)
val1 = 0
val2 = 0
調(diào)用構(gòu)造函數(shù)
val1 = 1000
val2 = 0
調(diào)用了拷貝賦值運(yùn)算符
val1 = 1000
val2 = 0
調(diào)用了析構(gòu)函數(shù)
調(diào)用了析構(gòu)函數(shù)

總結(jié)sum = 1000;這行代碼系統(tǒng)做了哪些事:

用1000這個(gè)數(shù)字創(chuàng)建了一個(gè)類型為CTempValue的臨時(shí)對(duì)象;調(diào)用拷貝賦值運(yùn)算符把這個(gè)臨時(shí)對(duì)象里面的各個(gè)成員值賦給了sum對(duì)象;銷毀這個(gè)剛剛創(chuàng)建的CTempValue臨時(shí)對(duì)象。

那如何優(yōu)化呢?

可以把main主函數(shù)中剛剛寫的兩行代碼優(yōu)化成下面一行:

CTempValue sum = 1000; //" = " 在這里不是賦值運(yùn)算符,而是定義初始化的概念

運(yùn)行結(jié)果如下:

調(diào)用構(gòu)造函數(shù)
val1 = 1000
val2 = 0
調(diào)用了析構(gòu)函數(shù)

可以看到,系統(tǒng)沒有生成臨時(shí)對(duì)象,所以系統(tǒng)少調(diào)用了一次構(gòu)造函數(shù),少調(diào)用了一次拷貝賦值運(yùn)算符、少調(diào)用了一次析構(gòu)函數(shù)。

1.2.2 隱式類型轉(zhuǎn)換以保證函數(shù)調(diào)用成功

int calc(const string& strsource, char ch)
{
    const char * p = strsource.c_str();
    int icount = 0;
    //......具體的統(tǒng)計(jì)代碼
    return icount;
}
//在main主函數(shù)的代碼如下:
int main()
{
    char mystr[100] = "I love China, oh, yeah!";
    int result = calc(mystr, 'o');
    return 0;
}

一個(gè)是char數(shù)組,一個(gè)是const string&,但是這個(gè)函數(shù)就能調(diào)用成功,為什么呢?

當(dāng)然是編譯器幫助我們做了一些事情,解決類型不匹配,那是如何做的呢?

那就是編譯器產(chǎn)生了一個(gè)類型sring的臨時(shí)對(duì)象,這個(gè)臨時(shí)對(duì)象的構(gòu)造方式就是用mystr作為參數(shù),調(diào)用了string的構(gòu)造函數(shù),這樣形參strsoutce就綁定到這個(gè)string臨時(shí)對(duì)象上了。當(dāng)calc函數(shù)返回的時(shí)候,這個(gè)臨時(shí)對(duì)象會(huì)被自動(dòng)銷毀。

C++只會(huì)為const string&(const引用)產(chǎn)生臨時(shí)對(duì)象,不會(huì)為string&(非const)產(chǎn)生臨時(shí)對(duì)象。

1.3 函數(shù)返回值的時(shí)候 - 如何優(yōu)化呢

我們在main主函數(shù)上面加一個(gè)普通的全局函數(shù):

CTempValue Double(CTempValue& ts)
{
    CTempValue tmpm;    //這里會(huì)消耗一次構(gòu)造函數(shù)和一次析構(gòu)函數(shù)的調(diào)用
    tmpm.val1 = ts.val1 * 2;
    tmpm.val2 = ts.val2 * 2;
    return tmpm; //這里會(huì)調(diào)用構(gòu)造函數(shù)和析構(gòu)函數(shù),這表示生成了一個(gè)臨時(shí)對(duì)象
}
int main()
{
    CTempValue ts1(10, 20);
    CTempValue ts2 = Double(ts1);  //其實(shí)臨時(shí)對(duì)象接管的就是右值
    CTempValue&& ts2 = Double(ts1);  
}

臨時(shí)對(duì)象就是一種右值

那如何優(yōu)化呢?

CTempValue Double(CTempValue& ts)
{
    return CTempValue(ts.val1 * 2, ts.val2 * 2); 
}

通過如上的優(yōu)化系統(tǒng)會(huì)調(diào)用一次拷貝構(gòu)造函數(shù),一次析構(gòu)函數(shù)。

二、小結(jié)

(1)寫代碼的時(shí)候,減少臨時(shí)變量的產(chǎn)生。

(2)鍛煉眼神,能夠盡量看出哪些地方可能會(huì)產(chǎn)生臨時(shí)對(duì)象,尤其是一個(gè)函數(shù)只要返回一個(gè)對(duì)象,一般機(jī)會(huì)產(chǎn)生臨時(shí)對(duì)象。

到此這篇關(guān)于解析C++中臨時(shí)對(duì)象的產(chǎn)生情況的文章就介紹到這了,更多相關(guān)C++臨時(shí)對(duì)象內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論