Effective C++ 第二十六條 Postpone variable definitions as long as pos
盡可能延后變量定義式的出現(xiàn)時(shí)間
本條例是為了節(jié)約開銷,提升效率而設(shè)置的。我們?cè)趯W(xué)習(xí)的過程中,或多或少看到過先定義再賦值的代碼,比如下面這樣
這種寫法不會(huì)引起錯(cuò)誤,但是可能會(huì)導(dǎo)致效率下降,比如定義了不會(huì)使用的變量,這樣的話我們要承擔(dān)這個(gè)變量的構(gòu)建和析構(gòu)的開銷,浪費(fèi)了 CPU 的周期。比如下面這樣
我們承擔(dān)了兩個(gè) int 和 一個(gè) string 的創(chuàng)建和釋放的開銷,但是沒起到絲毫作用(現(xiàn)代編譯器可能會(huì)將這樣的代碼優(yōu)化,將沒有影響最終結(jié)果的變量和計(jì)算過程都有化掉,但是我們不能依靠編譯器,得規(guī)范自己)。
有的時(shí)候不一定是我們故意定義沒用的變量,而是程序在運(yùn)行過程中出現(xiàn)異常,導(dǎo)致白白創(chuàng)建而沒使用就結(jié)束了。比如下面這樣
可能 encrypted 剛被創(chuàng)建,遇到異常,然后 throw 吐出異常,導(dǎo)致 string 創(chuàng)建毫無(wú)意義反而降低了CPU執(zhí)行效率。
優(yōu)化之后,可能你會(huì)想到是這樣
其實(shí)這個(gè)還不夠,因?yàn)檫@里的 encrypted 的創(chuàng)建還不夠延后,這里的 encrypted 創(chuàng)建是使用默認(rèn)構(gòu)造函數(shù),后面的代碼肯定還有賦值操作,也就是使用了一次默認(rèn)構(gòu)造,一次賦值操作。如果我在創(chuàng)建其的時(shí)候就使用拷貝構(gòu)造,那么效率會(huì)更高,也就是在時(shí)間上 一次默認(rèn)構(gòu)造+一次賦值操作 > 一次拷貝構(gòu)造。
這樣就會(huì)更好。
然后可能還有一種情況,就是面對(duì)循環(huán),變量究竟在循環(huán)內(nèi)定義還是循環(huán)外呢?
假設(shè) type 是一個(gè) class,對(duì)于 case 1,開銷是一個(gè)構(gòu)造函數(shù)、一個(gè)析構(gòu)函數(shù)、n個(gè)賦值操作,對(duì)于case 2,開銷是n個(gè)構(gòu)造函數(shù)、n個(gè)析構(gòu)函數(shù)。case 1 大體來(lái)說效率要更高,尤其當(dāng) n 很大的時(shí)候,如果n很小,case 2 更好。case 1 可能會(huì)帶來(lái)意外,因?yàn)?case 1 的 t 作用域更大,在 for 循環(huán)之后的代碼有誤操作的可能。因此對(duì)于 1 和 2 的選擇應(yīng)該考慮以下情況:
你知道 賦值 成本 小于 析構(gòu) + 構(gòu)造
你正在處理代碼中效率很敏感的部分
如果屬于上述兩種,選擇 case 1,否則選擇 case 2.