《劍指offer》面試題1:為類CMyString添加賦值運算符函數——C++拷貝構造函數與賦值函數


題中已給出CMyString的類定義,要求寫賦值運算符函數。

 1 #include<iostream>
 2 #include<cstring>
 3 using namespace std;
 4 
 5 class CMyString
 6 {
 7 public:
 8     CMyString(char* pdata = NULL);
 9     CMyString(const CMyString& rstring);
10     CMyString& operator = (const CMyString& rstring);
11     void Show();
12     ~CMyString();
13 private:
14     char* m_pdata;
15 };
16 
17 CMyString::CMyString(char* pdata) //這里不能寫char* pdata=NULL,一般如果函數聲明和定義分開,則默認參數值在聲明時                      //寫,定義時不用再寫了
18 {
19     /*m_pdata = pdata; 不能直接這樣賦值:如果這樣賦值,則新創建的m_pdata和pdata指向同一內存,m_pdata的操作直接影
20     影響pdata*/
21 
22     if(pdata == NULL)
23     {
24         m_pdata = NULL;
25         return;
26     }
27     int len = strlen(pdata);
28     m_pdata = new char[len + 1];
29     strcpy(m_pdata,pdata);
30 }
31 CMyString::CMyString(const CMyString& rstring)
32 {
33     int len = strlen(rstring.m_pdata);  //這里可以訪問rstring的私有成員m_pdata
34     m_pdata = new char[len + 1];
35     strcpy(m_pdata, rstring.m_pdata);
36 }
37 CMyString& CMyString::operator = (const CMyString& rstring)
38 {
39     if(this == &rstring)
40         return *this;
41     delete []m_pdata;
42     m_pdata = NULL;
43     m_pdata = new char[strlen(rstring.m_pdata)+1];
44     strcpy(m_pdata,rstring.m_pdata);
45 }
46 CMyString::~CMyString()
47 {
48     delete []m_pdata;
49 }
50 void CMyString::Show()
51 {
52     cout<<m_pdata<<endl;
53 }
54 int main()
55 {
56     char* pa = "abcde";
57     char* pb = "qperwdfaafda";
58     CMyString a(pa);
59     a.Show();
60     CMyString b(pb);
61     b.Show();
62     CMyString c(b);
63     c.Show();
64     a = c;
65     a.Show();
66     return 0;
67 }    

 

關於拷貝構造函數:
定義:
拷貝構造函數是一種特殊的構造函數,函數的名稱必須和類名稱一致,它的唯一的一個參數是本類型的一個引用變量,該參數是const類型,不可變的。例如:類X的拷貝構造函數的形式為X(X& x)。

調用情況:
當用一個已初始化過了的自定義類類型對象去初始化另一個新構造的對象的時候,拷貝構造函數就會被自動調用。也就是說,當類的 對象需要拷貝時,拷貝構造函數將會被調用。以下情況都會調用拷貝構造函數:
(1)一個對象以值傳遞的方式傳入函數體
(2)一個對象以值傳遞的方式從函數返回
(3)一個對象需要通過另外一個對象進行初始化。
例如:

String a(“hello”);
String b(“world”);
String c(a); //用已初始化過的a去初始化新對象c,調用拷貝構造函數
c = b; // 調用了賦值函數

拷貝構造函數中為什么可以調用參數的私有成員:
成員訪問控制符public、private、protected都是基於類而言的,如果一個類標記了private訪問權限,其意思是——這個類以外的其他類(友元類除外)無法訪問被private修飾的本類成員,但是本類自身是不受成員訪問符限制的。
class my;
my類中有一個private的成員num,其意思是——成員num對於my類以外的其他類(友元類除外)都不可見(或不可訪問),但my類自己並不受限於訪問權限。
拷貝構造函數的參數是同類的引用,屬於“本類”的范圍。

 

關於賦值函數:
賦值函數4步實現:
首先注意傳入的參數是const CMyString& rstring,常引用:
為什么是引用:如果參數不是引用而是實例,則從形參到實參相當於用已有對象去初始化一個新對象,要調用復制構造函數,造成不必要開銷。
為什么是const:因為賦值函數內不會改變傳入參數的狀態,因此應該為傳入的參數加上const。
(1)檢查自賦值:判斷傳入的參數和當前實例(*this)是否為同一個,如果是同一個則直接返回。沒有這一步的后果:一旦傳入的是自身,則在第二步會delete自己,一旦釋放自己的內存,參數也被釋放了(自殺后不能復制自己),因此找不到需要復制的內容了。
(2)用delete 釋放原有的內存資源。如果現在不釋放,以后就沒機會了,將造成內存泄露。
(3)分配新的內存資源,並復制字符串。
(4)返回本對象的引用:目的是為了實現stra = strb = strc這樣的連續賦值,如果是void則不能實現連續賦值。另外返回引用而不是實例也是為了避免調用拷貝構造函數。

 參考:

http://www.cnblogs.com/BlueTzar/articles/1223313.html  C++拷貝構造函數(深拷貝,淺拷貝)

http://blog.chinaunix.net/uid-25808509-id-354211.html   C++ 拷貝構造函數 賦值構造函數 


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com