C++中的賦值操作符重載和拷貝構造函數


1,關於賦值的疑問:

    1,什么時候需要重載賦值操作符?

    2,編譯器是否提供默認的賦值操作符?

   

2,關於賦值的疑問:

    1,編譯器為每個類默認重載了賦值操作符;

       1,意味着同類型的類對象可以相互賦值;

    2,默認的賦值操作符僅完成淺拷貝;

    3,當需要進行深拷貝時必須重載賦值操作符;

       1,和拷貝構造函數相同;

    4,賦值操作符與拷貝構造函數有相同的存在意義;

   

3,默認賦值操作符重載編程實驗:

    1,main.cpp 文件:

 1 #include <iostream>
 2 #include <string>
 3 
 4 using namespace std;
 5 
 6 class Test
 7 {
 8     int* m_pointer;
 9 public:
10     Test()
11     {
12         m_pointer = NULL;
13     }
14     Test(int i)
15     {
16         m_pointer = new int(i);
17     }
18     Test(const Test& obj)
19     {
20         m_pointer = new int(*obj.m_pointer);
21     }
22     Test& operator = (const Test& obj)  
23     {
24         if( this != &obj )  // 避免自賦值;
25         {
26             delete m_pointer;
27             m_pointer = new int(*obj.m_pointer);
28         }
29         
30         return *this;
31     }
32     void print()
33     {
34         cout << "m_pointer = " << hex << m_pointer << endl;
35     }
36     ~Test()
37     {
38         delete m_pointer;
39     }
40 };
41 
42 int main()
43 {
44     Test t1 = 1;
45     Test t2;
46     
47     t2 = t1;  // 默認賦值操作符的淺拷貝使得兩個對象內部指針指向同一片空間;
48 
49     int i = 0;  // C 語言中允許這樣,所以 C++ 中也必須允許;
50     i = i;
51 
52     t2 = t2;  // C++  中也要允許自賦值,但是沒有意義;
53     
54     t1.print();
55     t2.print();
56     
57     return 0;
58 }

 2,輸出結果:

  m_pointer = 0x9387008

  m_pointer = 0x9387018

 3,賦值操作符重載注意事項:

  1,賦值操作符返回值一定是引用,為了連續賦值;

  2,參數類型一定是 const Type&;

       3,不能自賦值;

       4,返回當前對象;

 

4,關於賦值的疑問:

 

    1,如果要進行深拷貝,拷貝構造函數和賦值操作符的實現都要自定義;

   

5,一般性原則:

    1,重載賦值操作符,必然要實現深拷貝;

       1,實現深拷貝和自定義賦值操作符及拷貝構造函數是充要條件;

   

6,數組類的優化編程實驗:

    1,IntArray.h 文件:

 1 #ifndef _INTARRAY_H_
 2 #define _INTARRAY_H_
 3 
 4 class IntArray
 5 {
 6 private:
 7     int m_length;
 8     int* m_pointer;
 9     
10     IntArray(int len);
11     IntArray(const IntArray& obj);
12     bool construct();
13 public:
14     static IntArray* NewInstance(int length); 
15     int length();
16     bool get(int index, int& value);
17     bool set(int index ,int value);
18     int& operator [] (int index);
19     IntArray& operator = (const IntArray& obj);
20     IntArray& self();
21     ~IntArray();
22 };

    2,首先寫出賦值操作符注意事項模板:

1 IntArray& IntArray::operator = (cosnt IntArray& obj)
2 {
3      if( this != &obj )
4      {
5          
6      }
7 
8      return *this;
9 }

    3,函數實現:

 1 IntArray& IntArray::operator = (const IntArray& obj)
 2 {
 3     if( this != &obj )
 4     {
 5         int* pointer = new int[obj.m_length];
 6         
 7         if( pointer )
 8         {
 9         /* 復制參數對象中的元素 */
10             for(int i=0; i<obj.m_length; i++)
11             {
12                 pointer[i] = obj.m_pointer[i];
13             }
14             
15         /* 深拷貝 */
16             m_length = obj.m_length;
17             delete[] m_pointer;
18             m_pointer = pointer;
19         }
20     }
21     
22     return *this;
23 }

 4,main.cpp 文件:

 1 #include <iostream>
 2 #include <string>
 3 #include "IntArray.h"
 4 
 5 using namespace std;
 6 
 7 int main()
 8 {
 9     IntArray* a = IntArray::NewInstance(5);   
10     IntArray* b = IntArray::NewInstance(10);
11     
12     if( a && b )
13     {
14         IntArray& array = a->self();
15         IntArray& brray = b->self();
16         
17         cout << "array.length() = " << array.length() << endl;
18         cout << "brray.length() = " << brray.length() << endl;
19     
20         array = brray;
21         
22         cout << "array.length() = " << array.length() << endl;
23         cout << "brray.length() = " << brray.length() << endl;
24     }
25     
26     delete a;
27     delete b;
28     
29     return 0;
30 }

 5,輸出結果:

1 array.length() = 5

2 brray.length() = 10

3 array.length() = 10

4 brray.length() = 10 

    6,使用二階構造后,拷貝構造函數是私有的,拷貝構造函數就沒有作用了,不允許拷貝構造,但是應該重載賦值操作符重載;

   

7,編譯器默認提供函數:

 

    1,雖然類中什么都沒寫,但是編譯器會放四個函數實現進去;

   

8,下面的代碼輸出什么?為什么?

    1,代碼示例:

1 string s = "12345";
2 const char* p = s.c_str();  // 返回字符指針,代表 C 語言中的字符串;
3 
4 cout << p << endl;
5 
6 s.append("abced");
7 
8 cout << p << endl;

   

9,字符串問題 1 編程實驗:

    1,main.cpp 文件:

 1 #include <iostream>
 2 #include <string>
 3 
 4 using namespace std;
 5 
 6 int main()
 7 {
 8     string s = "12345";
 9     const char* p = s.c_str();  // 只有這一行用了 C 方式;
10         
11     cout << p << endl;     
12         
13     s.append("abced");  // p 成為了野指針
14         
15     cout << p << endl;     
16 
17     return 0;
18 }

 2,這段代碼混合了 C 和 C++ 的方式,出了意想不到的錯誤;

   

10,關於 string 的疑問 1:

    1,string 對象內部維護了一個指向數據的 char* 指針,這個指針可能在程序     運行的過程中發生改變,我們盡量不要操作這個指針;

    2,執行 s.append() 函數后,char* 指針指向了新的堆空間 0xFF445566,而將舊的堆空間 0xFF112233 釋放,此時 p 指針成了野指針;

    3,學習 C++,並且用的是標准庫中的內容,所以現在采用的編程思想就應該是 C++ 編程思想,不要混合使用 C 和 C++ 思想;

   

11,下面的程序輸出什么?為什么?

    1,代碼示例:

 1 const char* p = "12345";  // p 可以用字符串對象代替;
 2 string s = "";  // 混合了,該注意了;
 3         
 4 s.reserve(10);
 5     
 6 // 不要使用 C 語言中的方式操作 C++ 中的字符串
 7 for(int i=0; i<5; i++)
 8 {
 9        s[i] = p[i];
10 }
11 
12 if( !s.empty() )
13 {
14     cout << s << endl;
15 }

    2,沒有輸出;

   

12,字符串問題 2 編程實驗:

    1,main.cpp 文件:

 1 #include <iostream>
 2 #include <string>
 3 
 4 using namespace std;
 5 
 6 int main()
 7 {
 8     const char* p = "12345";
 9     string s = "";
10         
11     s.reserve(10);
12     
13     // 不要使用 C 語言中的方式操作 C++ 中的字符串
14     for(int i=0; i<5; i++)
15     {
16         s[i] = p[i];
17     }
18 
19             if( !s.empty() )  // 打印不出;
20         {
21           cout << s << endl;
22         }
23 
24     cout << s << endl;  // 打印不出;
25 
26     for(int i=0; i<5; i++)  // 可以打印;
27     {
28         cout << s[i] << endl;
29     }
30     
31     return 0;
32 }

 2,更改程序為:

 1 #include <iostream>
 2 #include <string>
 3 
 4 using namespace std;
 5 
 6 int main()
 7 {
 8     const string p = "12345";
 9     string s = "";
10 
11     s = p;
12 
13     cout << s << endl;
14     
15     return 0;
16 }

 3,C++ 工程中,盡量避免指針使用,字符串類出現就是為了替代字符指針;

 

13,關於 string 的疑問 2:

 

14,小結:

    1,在需要進行深拷貝的時候必須重載賦值操作符;

       1,也要重新定義拷貝構造函數;

    2,賦值操作符和拷貝構造函數有同等重要的意義;

    3,string 類通過一個數據空間保存字符串數據;

    4,string 類通過一個成員變量保存當前字符串的長度;

    5,C++ 開發時盡量避開 C 語言中慣用的編程思想;

       1,字符串類得到的是字符串對象,直接用成員函數操作這個對象就可以,不需要用 C 語言中的 for 循環之類的;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM