C++Primer笔记之复制控制
復(fù)制控制這一節(jié)需要注意的地方不多,主要有以下幾點(diǎn):
1、定義自己的復(fù)制構(gòu)造函數(shù)
什么時(shí)候需要定義自己的復(fù)制構(gòu)造函數(shù),而不用系統(tǒng)提供的,主要遵循以下的經(jīng)驗(yàn)說明:
某些類必須對復(fù)制對象時(shí)發(fā)生的事情加以控制,這樣的類(1)經(jīng)常有一個(gè)數(shù)據(jù)成員是指針,(2)有成員在構(gòu)造函數(shù)中分配的其他資源;
而另一些類在創(chuàng)建對象時(shí)必須做一些特定的工作。
2、禁止復(fù)制
有些類是需要禁止復(fù)制的,如iostream類就不允許復(fù)制,但編譯器始終都會默認(rèn)合成一個(gè),但還是有辦法的:
為了防止復(fù)制,類只要顯示聲明其復(fù)制構(gòu)造函數(shù)為private就行了。
然而,這樣,類的友元和成員仍可以進(jìn)行復(fù)制,如果想要連友元和成員中的復(fù)制也禁止,就可以聲明一個(gè)private復(fù)制構(gòu)造函數(shù)但不對其定義,這是合法的。
3、析構(gòu)函數(shù)的異同
與復(fù)制構(gòu)造函數(shù)或賦值操作符不同,編譯器總是會為我們合成一個(gè)析構(gòu)函數(shù),合成析構(gòu)函數(shù)按照對象創(chuàng)建時(shí)的逆序撤銷每個(gè)非static成員。
析構(gòu)函數(shù)與復(fù)制構(gòu)造函數(shù)或賦值操作符之間的一個(gè)重要區(qū)別是:即使我們編寫了自己的析構(gòu)函數(shù),合成析構(gòu)函數(shù)仍然會運(yùn)行。合成析構(gòu)函數(shù)。
4、智能指針
智能指針是由于在有指針成員的類中,指針?biāo)赶虻膶ο笫枪蚕淼?#xff0c;防止出現(xiàn)懸垂指針而提出的一種管理指針的辦法。
為了闡述智能指針,我們來看一個(gè)例子:
1 class HasPtr{ 2 public: 3 HasPtr(int *p, int i):uptr(p), val(i) {} //p是指向int型數(shù)組的指針 4 HasPtr& operator = (const HasPtr& rhs); 5 int *getPtr() { 6 return uptr->ip; 7 } 8 int getValue() { 9 return val; 10 } 11 12 void setPtr(int *p) { 13 uptr->ip = p; 14 } 15 void setValue(int i) { 16 val = i; 17 } 18 19 int getPtrValue() const { 20 return *uptr->ip; 21 } 22 void setPtrValue(int i) { 23 *uptr->ip = i; 24 } 25 26 private: 27 int *uptr; 28 int val; 29 };如上一個(gè)類,如果我像這樣調(diào)用:
int obj = 0;
HasPtr ptr1(&obj, 42);
HasPtr ptr2(ptr1);
ptr1和ptr2的值相同,改變?nèi)我庖粋€(gè)的值都可以改變其共享對象的值。
再看,可能出現(xiàn)懸垂指針的情況:
int *ip = new int(42);
HasPtr ptr(ip, 10);
delete ip;
ptr.set_ptr_val(0); //Disaster!!!
這里ip和ptr中的指針指向了同一對象,刪除了該對象時(shí),ptr中的指針不再指向有效對象,但是你又不知道該對象不在了,所以,這樣就出現(xiàn)了懸垂指針。
所以,定義智能指針能有效地解決這個(gè)問題,為了避免多個(gè)指針共享一個(gè)對象時(shí)撤銷出現(xiàn)的懸垂指針問題,定義智能指針類的主要功能就是來保證在撤銷指向?qū)ο蟮淖詈笠粋€(gè)指針時(shí)才刪除該對象。
為了統(tǒng)計(jì)指向共享對象的指針的數(shù)量,引入使用計(jì)數(shù),用其跟蹤該類有多少個(gè)對象共享同一指針,但使用計(jì)數(shù)為0時(shí),刪除對象。在設(shè)計(jì)上,將使用計(jì)數(shù)設(shè)計(jì)成一個(gè)單獨(dú)的類,用來封裝使用計(jì)數(shù)和相關(guān)指針。
如下:
1 //僅由HasPtr使用的U_Ptr類,用于封裝使用計(jì)數(shù)和相關(guān)指針 2 class U_Ptr { 3 friend class HasPtr; //定義成友元 4 size_t use; 5 int *ip; 6 U_Ptr(int *p):ip(p), use(1) {} 7 ~U_Ptr() { delete ip; } 8 };引用上面的那個(gè)類,不同的是,讓HasPtr類保存一個(gè)指向U_Ptr對象的指針,U_Ptr對象再指向?qū)嶋H的int基礎(chǔ)對象。如下:
1 class HasPtr{ 2 public: 3 HasPtr(int *p, int i):uptr(new U_Ptr(p)), val(i) {} //p是指向int型數(shù)組的指針 4 HasPtr(const HasPtr& orig):uptr(orig.uptr),val(orig.val) { 5 ++uptr->use; //復(fù)制完成將使用計(jì)數(shù)加1 6 } 7 HasPtr& operator = (const HasPtr& rhs); 8 ~HasPtr() { 9 if(--uptr->use == 0) //檢查假如只有一個(gè)對象在共享該指針,則刪除 10 delete uptr; 11 } 12 13 int *getPtr() { 14 return uptr->ip; 15 } 16 int getValue() { 17 return val; 18 } 19 20 void setPtr(int *p) { 21 uptr->ip = p; 22 } 23 void setValue(int i) { 24 val = i; 25 } 26 27 int getPtrValue() const { 28 return *uptr->ip; 29 } 30 void setPtrValue(int i) { 31 *uptr->ip = i; 32 } 33 34 private: 35 U_Ptr *uptr; 36 int val; 37 };其中,紅色部分是改動過的。賦值操作符像下面這樣:
1 HasPtr& HasPtr::operator =(const HasPtr &rhs) 2 { 3 ++ rhs.uptr->use; 4 if (--uptr->use == 0) 5 delete uptr; 6 uptr = rhs.uptr; 7 val = rhs.val; 8 return *this; 9 }還有一種方法是定義值類型:
這種思路很簡單,就是給指針成員提供值語義,復(fù)制值型對象時(shí),會得到一個(gè)不同的新副本,對副本所做的改變不會反映在原有對象上。如下,可以對賦值操作符做點(diǎn)改變:
?
轉(zhuǎn)載于:https://www.cnblogs.com/bakari/p/3333797.html
總結(jié)
以上是生活随笔為你收集整理的C++Primer笔记之复制控制的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: solarized for secure
- 下一篇: 1019.Line Painting(线