午夜视频在线网站,日韩视频精品在线,中文字幕精品一区二区三区在线,在线播放精品,1024你懂我懂的旧版人,欧美日韩一级黄色片,一区二区三区在线观看视频

分享

為什么盡量使用初始化列表,而不要在構(gòu)造函數(shù)里賦值

 昵稱(chēng)7554924 2011-08-23
看這樣一個(gè)模板,它生成的類(lèi)使得一個(gè)名字和一個(gè) T 類(lèi)型的對(duì)象的指針關(guān)聯(lián)起來(lái)。
                                      template<class T>
                                      class NamedPtr {
                                         public:
                                        NamedPtr(const string& initName, T *initPtr);
                                          ...
                                        private:
                                       string name;
                                      T *ptr;
                                       };
         因?yàn)橛兄羔槼蓡T的對(duì)象在進(jìn)行拷貝和賦值操作時(shí)可能會(huì)引起指針混亂,NamedPtr 也必須實(shí)現(xiàn)這些函數(shù)在寫(xiě) NamedPtr 構(gòu)造函數(shù)時(shí),必須將參數(shù)值傳給相應(yīng)的數(shù)據(jù)成員。有兩種方法來(lái)實(shí)現(xiàn)。

         第一種方法是使用成員初始化列表:
         template<class T>
        NamedPtr<T>::NamedPtr(const string& initName, T *initPtr )
       : name(initName), ptr(initPtr)
        {}
          第二種方法是在構(gòu)造函數(shù)體內(nèi)賦值:
         template<class T>
        NamedPtr<T>::NamedPtr(const string& initName, T *initPtr)
       {
         name = initName;
          ptr = initPtr;
        }
         兩種方法有重大的不同。

        從純實(shí)際應(yīng)用的角度來(lái)看,有些情況下必須用初始化。特別是 const 和引用數(shù)據(jù)成員只能用初始化,不能被賦值。所以,如果想讓NamedPtr<T>對(duì)象不能改變它的名字或指針成員,就必須遵循條款21 的建議聲明成員為const:
template<class T>
class NamedPtr {
public:
NamedPtr(const string& initName, T *initPtr);
...
private:
const string name;
T * const ptr;
};
         這個(gè)類(lèi)的定義要求使用一個(gè)成員初始化列表,因?yàn)?const 成員只能被初始化,不能被賦值。如果 NamedPtr<T>對(duì)象包含一個(gè)現(xiàn)有名字的引用,情況會(huì)非常不同。但還是要在構(gòu)造函數(shù)的初始化列表里對(duì)引用進(jìn)行初始化。還可以對(duì)名字同時(shí)聲明const 和引用,這樣就生成了一個(gè)其名字成員在類(lèi)外可以被修改而在內(nèi)部是只讀的對(duì)象。
template<class T>
class NamedPtr {
public:
NamedPtr(const string& initName, T *initPtr);
...
private:
const string& name; // 必須通過(guò)成員初始化列表
// 進(jìn)行初始化
T * const ptr; // 必須通過(guò)成員初始化列表
// 進(jìn)行初始化
};
          然而前面最初的類(lèi)模板不包含const 和引用成員。即使這樣,用成員初始化列表還是比在構(gòu)造函數(shù)里賦值要好。這次的原因在于效率。當(dāng)使用成員初始化列表時(shí),只有一個(gè)string 成員函數(shù)被調(diào)用。而在構(gòu)造函數(shù)里賦值時(shí),將有兩個(gè)被調(diào)用。為了理解為什么,請(qǐng)看在聲明NamedPtr<T>對(duì)象時(shí)都發(fā)生了些什么。對(duì)象的創(chuàng)建分兩步:
         1. 數(shù)據(jù)成員初始化。
         2. 執(zhí)行被調(diào)用構(gòu)造函數(shù)體內(nèi)的動(dòng)作。
          對(duì)有基類(lèi)的對(duì)象來(lái)說(shuō),基類(lèi)的成員初始化和構(gòu)造函數(shù)體的執(zhí)行發(fā)生在派生類(lèi)的成員初始化和構(gòu)造函數(shù)體的執(zhí)行之前
          對(duì) NamedPtr 類(lèi)來(lái)說(shuō),這意味著string 對(duì)象name 的構(gòu)造函數(shù)總是在程序執(zhí)行到NamedPtr 的構(gòu)造函數(shù)體之前就已經(jīng)被調(diào)用了。問(wèn)題只在于:string 的哪個(gè)構(gòu)造函數(shù)會(huì)被調(diào)用?這取決于 NamedPtr 類(lèi)的成員初始化列表。如果沒(méi)有為name 指定初始化
參數(shù),string 的缺省構(gòu)造函數(shù)會(huì)被調(diào)用。當(dāng)在NamedPtr 的構(gòu)造函數(shù)里對(duì)name執(zhí)行賦值時(shí),會(huì)對(duì)name 調(diào)用operator=函數(shù)。這樣總共有兩次對(duì)string 的成員函數(shù)的調(diào)用:一次是缺省構(gòu)造函數(shù),另一次是賦值。相反,如果用一個(gè)成員初始化列表來(lái)指定name 必須用initName 來(lái)初始化,name 就會(huì)通過(guò)拷貝構(gòu)造函數(shù)以?xún)H一個(gè)函數(shù)調(diào)用的代價(jià)被初始化。

        即使是一個(gè)很簡(jiǎn)單的 string 類(lèi)型,不必要的函數(shù)調(diào)用也會(huì)造成很高的代價(jià)。隨著類(lèi)越來(lái)越大,越來(lái)越復(fù)雜,它們的構(gòu)造函數(shù)也越來(lái)越大而復(fù)雜,那么對(duì)象創(chuàng)建的代價(jià)也越來(lái)越高。養(yǎng)成盡可能使用成員初始化列表的習(xí)慣,不但可以滿足const 和引用成員初始化的要求,還可以大大減少低效地初始化數(shù)據(jù)成員的機(jī)會(huì)。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶(hù)發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶(hù) 評(píng)論公約

    類(lèi)似文章 更多