今天把c++ primer的13章看了,總結一下。
一:複製控制
1:複製控制就是複製建構函式、賦值操作符、解構函式的總稱。他們有一定的相似性,所以統稱為“複製控制”。
他們的共性是什麼呢?
a:如果自己沒定義,系統會自動合成;
b:對於類的對象成員中有指標的情況,一般都要定義這三者。而且如果要定義解構函式就一定要定義複製建構函式和賦值操作符,這個叫“三法則”。
不同點:
複製建構函式和賦值操作符如果自己定義了,系統就不會合成,但是解構函式系統始終會合成。(p-414)利用複製建構函式和賦值操作符的特點,可以對於不能夠賦值的進行避免賦值。我們可以只申明不定義,這樣可以避免系統合成,我們自己也不操作就達到了目的。
2:為什麼要用複製建構函式
什麼時候要定義複製建構函式和賦值操作符
一般來講,當類的資料成員有指標變數,或者對對象有特殊操作時需要定義複製建構函式和賦值操作符。下面是個類的資料成員有指標變數的列子。
程式如下:
#include <stdio.h>#include <string>#include <iostream>using namespace std;struct NoName{public:NoName(std::string *str_f,int i_f,double d_f):pstring(str_f),i(i_f),d(d_f){};NoName(const NoName &a){pstring=new std::string;*(this->pstring)=*(a.pstring);this->i=a.i;this->d=a.d;}public:std::string *pstring;int i;double d;};int main(){string a(4,'x');string b(4,'y');string *str_a=&a;//string和數組還不同NoName Object1(str_a,2,3.0);NoName Object2(Object1);*(Object2.pstring)=b;cout<<*(Object1.pstring)<<endl;system("pause");return 1;}
對於這種含有指標成員的類,因為在複製是只複製指標地址,所以他們其實是公用一個基的。這種改變內容而改變其他對象的內容到不可怕,可怕的是在刪除時引起的指標懸掛。
二、指標懸掛與智能指標
指標懸掛也稱為“野指標”,是只在指標所指記憶體被刪除後指標的指向不確定的情況。對於這種指標,我們其實是可以訪問的,但是得到的值不一定每次一樣,因為這時候指標指的方向其實是不定的。但是我們不能對其所指內容進行操作,比如修改裡面的值或者刪除等等。也就是說,看看可以,但是沒有操作許可權。
為瞭解決指標懸掛,可以由兩種方法。
a:構造複製建構函式
這種方法是對於每個指標就行複製操作,這樣通過改變其他對象的指標就不能影響到別的。
b:利用智能指標
智能指標可以解決指標懸掛的問題,但是其不能解決因為改變一個對象的值而影響其他對象值的問題。那麼什麼是智能指標呢?在c++ primer(p-423)中很清楚的闡明了什麼是智能指標和怎麼構造一個智能指標。其代碼如下:
class U_Ptr{friend class HasPtr;U_Ptr(int *p):ip(p),use(1){}~U_Ptr(){delete ip;}int *ip;size_t use;};class HasPtr{public:HasPtr(int *p,int i):ptr(new U_Ptr(p)),val(i){}HasPtr(const HasPtr &orig):ptr(orig.ptr),val(orig.val){orig.ptr->use++;}HasPtr& operator=(const HasPtr &rhs);~HasPtr(){if(--ptr->use==0) delete ptr;}private:U_Ptr *ptr;int val;};HasPtr& HasPtr::operator =(const HasPtr &rhs){rhs.ptr->use++;if(--this->ptr->use==0)delete this;this->ptr=rhs.ptr;this->val=rhs.val;return *this;}
這裡說明一下幾點:
1:智能指標是連絡人物件和所屬單元的紐帶,其本質上是起一個過渡作用;
2:智能指標只用於HasPtr類,我們並不希望使用者用它。因此,我們把其所有資料定義為private,並且把HasPtr定義為其友元;
3:在這裡補充兩點與上沒有關係的兩個知識點:
1):new U_Ptr(p)是建立一個U_Ptr對象,其參數要求是和U_Ptr的建構函式形式息息相關的;
2):友元類表達的意思是可以讓友元類中該對象訪問其類中的私人函數,也就是說任何類的成員只能其對象才可以訪問,這點是沒有商量的餘地的。
三:補充介紹一下賦值操作符和解構函式
賦值操作符和複製建構函式情況差不多,這裡略去。主要介紹一下解構函式。
1:解構函式的作用
解構函式和建構函式相對應,其是用於釋放空間的。但是因為一般系統會自動合成解構函式,那麼我們在什麼情況下還需要自己定義解構函式呢?
2:什麼時候定義解構函式
對於“對象引用或者對象指標”和“動態申請的對象”需要手動刪除,這時候一般就需要用解構函式。或者我們想在對象刪除的同時,做點其他動作,這是也可以通過解構函式完成。而其他一般都可以通過解構函式解決。