• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            隨筆-59  評論-36  文章-0  trackbacks-0

            看完ISO C++ 12.8一節后,做如下筆記。


            當一個類對象被用來初始化或賦值時會通過該類的復制構造或重載賦值操作符被復制。

            復制構造函數
            1.類A的復制構造函數不能是模板,模板復制構造函數不會阻止默認復制構造的生成。復制構造函數可以有不止一個參數,但不論有幾個參數,其第一個參數必須是A &、const A &、volatile A &或const volatile A &型之一(均不能為非引用型),其他形參必須有默認實參,且默認實參必須出現在復制構造函數的聲明中。這是因為對于:
            classX
            {
            public:
             X(const X&, int);
            };
            X::X(const X& ,int = 9){}
            因為如果沒有在類的定義體中沒有顯示的聲明一個復制構造函數,編譯器將自動隱士聲明一個。所以盡管在實現中對第二個參數提供了默認實參,但由于類中沒有顯示的聲明復制構造函數,于是編譯器便認該類中沒有聲明復制構造,所以將隱士的聲明一個。這樣一來,任何對該類的復制構造的調用都將使用編譯器自己生成的。例如下面代碼

            class T
            {
             
            public:
             T();
             T(
            const T&,int);
            }
            ;

            T::T()
            {}
            T::T(
            const T&,int=7)
            {
             cout 
            << "T(const T&,int=7)"<<endl;
            }



            int main()
            {
             T one;
             T two (one);
            }


            //GCC4.4中產生T::T(const T&, int)與T::T(const T&)的二義性;VC2005中則沒有產生二義性,直接調用T(const T&,int)

             

            2.如果類T的每一個直接基類或虛基類的復制構造函數的第一個參數類型中含有const限定符,且對于類T中所有類類型的非靜態數據成員,當該數據成員所屬的類中的復制構造函數的第一個參數類型中含有const限定符時,T類的隱士聲明的復制構造函數的格式為T::T(const T&)。否則T類的隱士聲明的復制構造函數的格式為T::T(T&)
            同時,隱式聲明的復制構造函數是inline public。同時隱式聲明的復制構造函數擁有異常說明。
            P.S.: 隱式聲明的復制構造函數的參數類型中不包含volatile限定符,即只能是T& 或const T & ,不能是volatile T& 或volatile const T&

            3.當類T中有隱士聲明的復制構造函數,且沒有虛函數、沒有虛基類、含有trivial復制構造函數的基類以及該類T的非靜態類類型數據成員所屬的類中有trivial復制構造函數時,則稱T的復制構造函數為trivial,否則為nontrivial

            4.當隱士聲明的復制構造函數用于對該函數所屬類的對象進行初始化時將被隱士定義,即便編譯器優化掉對復制構造函數的調用。
            一個有隱士定義的復制構造函數的類T,如果滿足以下情況之一時則是不規范的:
               該T類的非靜態類類型數據成員中有不可訪問的或存在二義性的復制構造函數;
               該T類的基類中有不可訪問的或存在二義性的復制構造函數時。
            在一個隱式聲明的復制構造函數被隱士定義之前,其所屬類的直接/虛基類和非靜態數據成員中隱式聲明的的復制構造函數都應完成隱式定義

            5.隱式定義的復制構造函數對類中的子對象將執行深拷貝(memberwise copy)。執行順序與用戶自定義中基類和成員的初始化順序一樣。
            執行過程:對類對象,調用該類中的復制構造函數;對內置數據類型,調用內置的賦值操作符
            另,隱士定義的復制構造函數應該只復制虛基類一次。


            拷貝賦值操作符
            1.類T的一個用戶定義的拷貝賦值操作符是一個非靜態非模板成員函數(模板的賦值操作符并不會阻止編譯器自行隱士生成賦值操作符函數),該函數只能有一個形參(即便多出的參數有默認實參)且形參類型是T &、const T &、volatile T &或const volatile T &之中的一個。可以存在多個賦值操作符。
            如果沒有顯示的聲明拷貝賦值操作符,編譯器將隱士生成一個。同時,對于該隱士生成的拷貝賦值操作符來說,如果類T中的每一個直接基類的拷貝賦值操作符的形參類型中含有const限定符,且如果類T的所有非靜態類類型數據成員所屬類中的拷貝賦值操作符的形參類型中含有const限定符,則類T的拷貝賦值操作符的形參類型為const T &,否則為T &.
            與隱士聲明的復制構造函數一樣,隱士聲明的賦值操作符是inline public。
            另,因為拷貝賦值操作符的隱士聲明是在用戶沒有聲明時進行的,以及派生類的賦值操作符會隱藏基類的賦值操作符。所以,通過using聲明從派生類的基類中引入一個參數類型為該派生類的賦值操作符仍會被該派生類中隱式聲明的賦值操作符所隱藏。如下代碼:

            class T;
            class A
            {
            public:

             
            void operator=(T&)
             
            {
              cout 
            << "&operator=(T&)"<<endl;
             }

            }
            ;

            class T: public A
            {
             
            public:

             
            using A::operator=;
            }
            ;



            int main()
            {
             T one,two;
             one
            = two;
            }


            //GCC4.4中輸出"&operator=(T&)",而VC2005中沒有任何輸出。說明對于“隱士聲明的隱藏由using聲明引入基類中的賦值操作符”這一行為,GCC中沒有遵守,而VC遵從了。

             

            2.與復制構造函數一樣,當一個類有隱式聲明的拷貝賦值操作符,并且沒有虛函數、沒有虛基類、每一個直接基類有一個trivial拷貝賦值操作符、且所有非靜態類類型數據成員所屬的類中有一個trivial拷貝賦值操作符時,該隱式聲明的拷貝賦值操作符為trivial,否則其他情況下都為nontrivial。

            3.當有用到賦值操作符時隱士聲明的賦值操作符將隱士定義。對于有隱士定義的賦值操作符的類,如果該類有const限定的非靜態數據成員、或有非靜態數據成員的引用類型、或有非靜態類類型的數據成員所屬的類中的有不可訪問的賦值操作符,或有基類中有不可訪問的賦值操作符時,是不規范的。
            同時在隱士聲明的賦值操作符被隱士定義之前,該類中的所有基類以及非靜態數據成員都應該完成隱士定義。另,隱士聲明的賦值操作符有異常說明符。

            4.隱士定義的賦值操作符執行深度賦值(memberwise assignment)。對基類的賦值順序與基類派生列表中的順序一樣,而非靜態數據成員則以他們在類中定義的順序賦值。
            每個子對象的賦值都是以特定的方式進行:
            如果子對象為類類型,則調用其所屬類中的賦值操作符;如果是內置類型,則使用內置的賦值操作符
            注意:并沒有說明隱式定義的賦值操作符對虛基類賦值幾次


            參考:ISO C++ 12.8

            posted on 2009-10-07 20:25 zhaoyg 閱讀(485) 評論(0)  編輯 收藏 引用 所屬分類: C/C++學習筆記
            99麻豆久久久国产精品免费| 久久国产精品一区| av色综合久久天堂av色综合在| 久久久久久久亚洲精品| 久久亚洲AV永久无码精品| 久久久久国产精品嫩草影院| 久久亚洲精品国产亚洲老地址| 亚洲欧美成人久久综合中文网 | 亚洲国产小视频精品久久久三级| 亚洲人成电影网站久久| 久久久久99精品成人片直播| 一本一道久久精品综合| 久久中文骚妇内射| 久久伊人精品青青草原高清| 欧美一级久久久久久久大| 亚洲午夜久久久久妓女影院| 色偷偷888欧美精品久久久| 午夜精品久久久内射近拍高清| 久久夜色精品国产噜噜麻豆| 国产成人精品久久亚洲高清不卡| 久久人妻少妇嫩草AV蜜桃| 亚洲综合婷婷久久| 亚洲精品无码久久久影院相关影片| 婷婷综合久久狠狠色99h| 久久久久久久女国产乱让韩| 国产高潮久久免费观看| 无码日韩人妻精品久久蜜桃| 久久亚洲色一区二区三区| 国产国产成人精品久久| 亚洲午夜久久久久久久久电影网 | 色悠久久久久久久综合网| 久久精品成人国产午夜| 天天躁日日躁狠狠久久| 婷婷久久精品国产| 久久久久久国产a免费观看不卡| 国产午夜久久影院| 91精品国产乱码久久久久久| 久久永久免费人妻精品下载| 久久天天躁狠狠躁夜夜躁2O2O | 亚洲精品国产综合久久一线| 久久精品国产精品亚洲艾草网美妙|