• <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>
            posts - 183,  comments - 10,  trackbacks - 0

            swap 到底做了什么
            swap 交換兩個內置數據類型的變量時,直接交換。
            swap 交換自定義類型對象時,如果里面沒有成員指針,直接交換各個對應成員。
            如果自定義類型中有指針成員,則是交換兩個指針的值,但是指針的指向的值得不到交換。
            正是由于這個原因,可以用 swap 進行重載 operator = 時避免自賦值情況,而是生產一個臨時對象,然后與本對象 swap 即可。

            關于重載 operator = 自賦值的情況,更詳細內容可以查看《Effective C++》
            實驗程序:

              1 #include <iostream>
              2 using namespace std;
              3 
              4 class Str
              5 {
              6 private:
              7     char* s_;
              8 public:
              9     Str(const char* s = "")
             10     {
             11         s_ = new char[strlen(s) + 1];
             12         if (s_ == 0)
             13         {
             14             cout << "test" << endl;
             15             exit(1);
             16         }
             17         strcpy(s_, s);
             18     }
             19     // 定義拷貝構造函數,這里會被用于 operator =,swap
             20     Str(const Str& rhs)
             21     {
             22         s_ = new char[strlen(rhs.s_) + 1];
             23         if (s_ == 0)
             24         {
             25             cout << "test" << endl;
             26             exit(1);
             27         }
             28         strcpy(s_, rhs.s_);
             29     }
             30     ~Str()
             31     {
             32         clear();
             33     }
             34     //// 常規的 operator = 重載實現方式,必須檢查自賦值
             35     //// 因為如果不自賦值檢驗,對于自賦值現象如果不調用 clear,則 s_ 在 new 之后就改變,rhs 也改變,原來的丟失,后來的也不是合法內容
             36     //// 如果調用 clear,不會內存泄露,但是 rhs 的內容被釋放掉,rhs 的內容也不是合法內容。
             37     //// 如果檢驗自賦值,而沒有 clear,原來 *this 的那塊內存會被丟失,造成內存泄露。
             38     //Str& operator = (const Str& rhs)
             39     //{
             40     //    if (this != &rhs)
             41     //    {
             42     //        clear();
             43     //        s_ = new char[strlen(rhs.s_) + 1];
             44     //        if (s_ == 0)
             45     //        {
             46     //            exit(1);
             47     //        }
             48     //        strcpy(s_, rhs.s_);
             49     //    }
             50     //    return *this;
             51     //}
             52 
             53     // 改進的 operator,先用一個 temp 保持 rhs,然后 swap
             54     // 這種方式不怕自賦值,因為如果是自賦值,也有一個備份 temp,操作值相同的兩個對象 *this 和 temp,直接交換不會影響結果
             55     // 如果不是自賦值,不是交換 *this 和 rhs,而是交換 *this 和 rhs 的一個復制品 temp,最終 *this 得到的值就是 rhs 的一個副本,完成賦值
             56     // 這種方式不用檢驗自賦值,所以可以省去每次調用時的自賦值檢驗,在基本上不會遇到自賦值檢驗的情況下,這種方法可以省去很多誤用的檢驗
             57     // 但是它會每次生成一個副本,這樣做的效率與原來的非自賦值一樣,而且還需要一個 swap,但是這種方式是異常安全的,用對象來管理資源,資源分配即初始化
             58     Str& operator = (const Str& rhs)
             59     {
             60         cout << "test" << endl;
             61         Str temp(rhs);
             62         // swap(*this, temp);
             63         // 這里會引起遞歸調用,因為 operator = 調用 swap,swap 內部又調用 operator = ,一直遞歸下去,直到棧溢出
             64         swap(s_, temp.s_);
             65         // Effective C++ 中提到,可以定義一個成員函數 swap,用于交換兩個對象對應的數據成員。這樣可以防止無限遞歸。
             66         // 另一種好的方式是除定義一個成員函數 swap 外,傳參類型為 值類型 T,這樣就可以直接交換返回。
             67         // 這些方法的前提都是要有定義拷貝構造函數的。
             68         return *this;
             69     }
             70 
             71     void clear()
             72     {
             73         delete [] s_;
             74     }
             75     void foo()
             76     {
             77         cout << s_ << endl;
             78     }
             79 };
             80 
             81 int main()
             82 {
             83     int a = 3, b = 5;
             84     swap(a, b);
             85     cout << a << endl;
             86     cout << b << endl;
             87 
             88     Str s1("abc");
             89     Str s2("xyz");
             90     s1.foo();
             91     s2.foo();
             92 
             93     swap(s1, s2);
             94     // 這里輸出兩個 test,我們得知,有兩個賦值操作
             95     // 可以推測 swap 的內部實現是 T t(s2), s2 = s1, s1 = t;
             96     s1.foo();
             97     s2.foo();
             98 
             99     s2 = s1;
            100     s1.foo();
            101     s2.foo();
            102 
            103     return 0;
            104 }


            posted on 2011-05-27 22:14 unixfy 閱讀(890) 評論(0)  編輯 收藏 引用
            国产成人精品久久综合| 一级A毛片免费观看久久精品| 国产∨亚洲V天堂无码久久久| 精品久久久久久久无码| 狠狠色伊人久久精品综合网| 亚洲国产精品狼友中文久久久| 久久久噜噜噜久久中文字幕色伊伊| 久久香蕉国产线看观看精品yw| 久久久久人妻一区精品性色av| 国产精品99久久久久久猫咪 | 亚洲狠狠久久综合一区77777| 精品久久久久久无码中文野结衣 | 麻豆国内精品久久久久久| 久久国语露脸国产精品电影 | 国产精品久久久久久久app| 99久久国产综合精品麻豆| 久久久久久久久久免免费精品| 亚洲国产精品18久久久久久| 国产香蕉97碰碰久久人人| 色综合久久无码五十路人妻| 久久精品亚洲福利| 久久精品国产亚洲网站| 蜜臀av性久久久久蜜臀aⅴ| 免费精品国产日韩热久久| 国产精品青草久久久久福利99| 欧洲人妻丰满av无码久久不卡| 少妇久久久久久被弄到高潮| 狠狠久久亚洲欧美专区| 亚洲AV无码成人网站久久精品大| 久久久久国产精品三级网| 2020最新久久久视精品爱| 精品国产91久久久久久久| 久久精品蜜芽亚洲国产AV| 一本色道久久88—综合亚洲精品| 亚洲性久久久影院| 狠狠色丁香婷婷久久综合五月| 欧美日韩成人精品久久久免费看| 久久99精品国产麻豆蜜芽| 66精品综合久久久久久久| 国产成人精品久久亚洲高清不卡 国产成人精品久久亚洲高清不卡 国产成人精品久久亚洲 | 97久久香蕉国产线看观看|