• <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>

            寶杉的博客

            UNIX/LINUX;ACE;SNMP;C++
            posts - 33, comments - 23, trackbacks - 0, articles - 0

            08-14 String類

            Posted on 2007-08-30 10:31 寶杉 閱讀(278) 評論(0)  編輯 收藏 引用 所屬分類: C++

            定義:

                 class String

                 {

                   public:

                     String(const char *str = NULL);  // 普通構造函數

                     String(const String &other);     // 拷貝構造函數

                     ~ String(void);                       // 析構函數

                     String & operate =(const String &other);  // 賦值函數

                   private:

                     char     *m_data;               // 用于保存字符串

                 };

             

             

            普通構造:

                     // String的普通構造函數

                     String::String(const char *str)

            {

                 if(str==NULL)

                 {

                     m_data = new char[1];

                     *m_data = \0;

                 }   

                 else

                 {

                     int length = strlen(str);

                     m_data = new char[length+1];

                     strcpy(m_data, str);

                 }

            }   

            注意在聲明時,才定義的參數,且賦初值為NULL。在拷貝函數內部,也進行了是否為NULL的檢查,進行特殊處理。

             

             

            析構函數:

            // String的析構函數

                     String::~String(void)

            {

                 delete [] m_data; 

            // 由于m_data是內部數據類型,也可以寫成 delete m_data;

                     }

            內部數據類型,delete

            外部數據類型,[ ] delete

             

            拷貝構造函數與賦值函數:

            拷貝函數:

            位拷貝:編譯器以此方式自動生成缺省的函數,比如構造拷貝和賦值拷貝。但是,如果函數中還有指針變量,那么缺省的函數就隱含了錯誤。

            例如:

            以類String的兩個對象a,b為例,假設a.m_data的內容為“hello”,b.m_data的內容為“world”。

            現將a賦給b,缺省賦值函數的“位拷貝”意味著執行b.m_data = a.m_data

            這將造成三個錯誤:

            一是b.m_data原有的內存沒被釋放,造成內存泄露;

            二是b.m_dataa.m_data指向同一塊內存,ab任何一方變動都會影響另一方;

            三是在對象被析構時,m_data被釋放了兩次。

            混淆:

            String  a(hello);

            String  b(world);

            String  c = a;     // 調用了拷貝構造函數,最好寫成 c(a);

            c = b;    // 調用了賦值函數

            例子:

                 // 拷貝構造函數

                 String::String(const String &other)

                 {   

            // 允許操作other的私有成員m_data

                 int length = strlen(other.m_data);  

                 m_data = new char[length+1];

                 strcpy(m_data, other.m_data);

            }

            賦值函數:

            // 賦值函數

                 String & String::operate =(const String &other)

                 {   

                     // (1) 檢查自賦值

                     if(this == &other)

                          return *this;

                    

                     // (2) 釋放原有的內存資源

                     delete [] m_data;

                    

                     // 3)分配新的內存資源,并復制內容

                 int length = strlen(other.m_data);  

                 m_data = new char[length+1];

                      strcpy(m_data, other.m_data);

                    

                     // 4)返回本對象的引用

                     return *this;

            }   

            賦值函數的四個步驟:

            (1) 檢查自賦值

            不會寫出a = a的自賦值語句,但間接自賦值有可能發生。

            // 內容自賦值

            b = a;

            c = b;

            a = c;  

            // 地址自賦值

            b = &a;

            a = *b;

            防止:

            if(this == &other)

            錯寫成為

                 if( *this == other)

            (2) 釋放原有的內存資源

            (3) 分配新的內存資源,并復制內容

            (4) 返回本對象的引用

             

            F:拷貝構造和普通構造的區別?

            Q:拷貝構造的參數是“引用”,引用不可能是NULL;普通構造函數參數是“指針”,需要類型檢查,判斷是否是NULL

             

            String的賦值函數比構造函數復雜得多,分四步實現:

            1)第一步,檢查自賦值。你可能會認為多此一舉,難道有人會愚蠢到寫出 a = a 這樣的自賦值語句!的確不會。但是間接的自賦值仍有可能出現,例如

                

            // 內容自賦值

            b = a;

            c = b;

            a = c;  

            // 地址自賦值

            b = &a;

            a = *b;

             

            也許有人會說:“即使出現自賦值,我也可以不理睬,大不了化點時間讓對象復制自己而已,反正不會出錯!”

            他真的說錯了。看看第二步的delete,自殺后還能復制自己嗎?所以,如果發現自賦值,應該馬上終止函數。注意不要將檢查自賦值的if語句

            if(this == &other)

            錯寫成為

                 if( *this == other)

            2)第二步,用delete釋放原有的內存資源。如果現在不釋放,以后就沒機會了,將造成內存泄露。

            3)第三步,分配新的內存資源,并復制字符串。注意函數strlen返回的是有效字符串長度,不包含結束符‘\0’。函數strcpy則連‘\0’一起復制。

            4)第四步,返回本對象的引用,目的是為了實現象 a = b = c 這樣的鏈式表達。注意不要將 return *this 錯寫成 return this 。那么能否寫成return other 呢?效果不是一樣嗎?

            不可以!因為我們不知道參數other的生命期。有可能other是個臨時對象,在賦值結束后它馬上消失,那么return other返回的將是垃圾。

             

             

            08-22

            如果不想讓別人使用編譯器編寫構造拷貝和賦值函數,可以聲明為私有:

                 class A

                 {

                   private:

                     A(const A &a);                   // 私有的拷貝構造函數

                     A & operate =(const A &a);  // 私有的賦值函數

                 };

             

            如果有人試圖編寫如下程序:

                 A  b(a); // 調用了私有的拷貝構造函數

                 b = a;        // 調用了私有的賦值函數

            編譯器將指出錯誤,因為外界不可以操作A的私有函數。

            但是怎樣才能使用構造拷貝和賦值函數呢?

            虛擬函數使用:C++exams\destructor

             

            在編寫派生類的賦值函數時,注意不要忘記對基類的數據成員重新賦值。例如:

            C++exams\base_operator

             

            久久99这里只有精品国产| 久久国产精品99久久久久久老狼| 狠狠色伊人久久精品综合网| 国产呻吟久久久久久久92| 人妻精品久久久久中文字幕| 亚洲AV无码成人网站久久精品大| 高清免费久久午夜精品| 久久久久久久91精品免费观看| 久久亚洲私人国产精品| 久久久久久国产精品免费免费| 国内精品久久久久影院薰衣草| 国产精品久久久久久久久鸭 | 国产日韩久久久精品影院首页| 亚洲午夜精品久久久久久app| 国产精品美女久久久久| 四虎亚洲国产成人久久精品| 久久中文娱乐网| 久久AV高潮AV无码AV| 久久福利片| 99久久99这里只有免费的精品| 超级碰碰碰碰97久久久久| 青青青国产成人久久111网站| 午夜欧美精品久久久久久久| 久久国产成人精品国产成人亚洲| 久久精品国产亚洲AV无码娇色| 精品久久久久久无码不卡| 久久播电影网| 91精品国产色综久久| 久久国产精品久久精品国产| 久久这里只有精品18| 亚洲国产精品18久久久久久| 伊人久久无码精品中文字幕| 人人狠狠综合久久亚洲| 久久久久国产成人精品亚洲午夜| 狠狠色丁香婷综合久久| 狠狠色丁香久久婷婷综| 粉嫩小泬无遮挡久久久久久| 97久久精品人妻人人搡人人玩| 久久天天躁狠狠躁夜夜96流白浆| 久久精品国产久精国产一老狼| 国内精品伊人久久久影院|