chp4-類的高級特性_第1頁
chp4-類的高級特性_第2頁
chp4-類的高級特性_第3頁
chp4-類的高級特性_第4頁
chp4-類的高級特性_第5頁
已閱讀5頁,還剩23頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

第四章類的高級特性第四章類的高級特性24.1案例-鏈表類的復制問題4.1.1案例及其實現(xiàn)復雜類型的復制操作a:1b:2.3a:?b:?o1o2復制復制的兩種方式:Xo2{o1};o2=o1;a:1b:2.3可以視為是內存復制第四章類的高級特性linked_list::linked_list():head(nullptr),tail(nullptr),_size(0){std::cout<<"indefaultconstructor"<<std::endl;}

linked_list::linked_list(conststd::initializer_list<value_t>&l):head(nullptr),tail(nullptr),_size(0){for(autoe:l)push_back(e);std::cout<<"inlistconstructor"<<std::endl;}

linked_list::~linked_list(){clear();std::cout<<"indestructor"<<std::endl;}34.1案例-鏈表類的復制問題4.1.1案例及其實現(xiàn)鏈表的構造函數(shù)和析構函數(shù)第四章類的高級特性voidlinked_list::peer(){std::cout<<"|"<<head<<''<<tail<<''<<_size<<std::endl;}intmain(){autoaf=[](value_t&v){std::cout<<v<<'';};linked_listl1{1,2,3,4,5};//定義對象并初始化std::cout<<"l1:";l1.traverse(af);l1.peer();

linked_listl2{l1};//初始化復制std::cout<<"l2:";l2.traverse(af);l2.peer();

return0;}44.1案例-鏈表類的復制問題4.1.1案例及其實現(xiàn)鏈表的復制—初始化時有兩個對象定義,因此應該有兩條構造和析構信息inlistconstructorl1:12345|0x6020000000100x6020000000905l2:12345|0x6020000000100x6020000000905indestructor===================================================================5430==ERROR:AddressSanitizer:attemptingdouble-freeon0x602000000010inthreadT0:#00x7fe3dff1e0f8inoperatordelete(void*,unsignedlong)../../../../libsanitizer/asan/asan_new_delete.cc:151#10x40100finlinked_list::clear()…//此后是詳細的診斷信息,故略去第四章類的高級特性voidlinked_list::peer(){std::cout<<"|"<<head<<''<<tail<<''<<_size<<std::endl;}intmain(){autoaf=[](value_t&v){std::cout<<v<<'';};linked_listl1{1,2,3,4,5};//定義對象并初始化std::cout<<"l1:";l1.traverse(af);l1.peer();

linked_listl2;

l2

=

l1;

//賦值std::cout<<"l2:";l2.traverse(af);l2.peer();

return0;}54.1案例-鏈表類的復制問題4.1.1案例及其實現(xiàn)鏈表的復制—賦值時有兩個對象定義,因此應該有兩條構造和析構信息inlistconstructorl1:12345|0x6020000000100x6020000000905indefaultconstructorl2:12345|0x6020000000100x6020000000905indestructor===================================================================5430==ERROR:AddressSanitizer:attemptingdouble-freeon0x602000000010inthreadT0:#00x7fe3dff1e0f8inoperatordelete(void*,unsignedlong)../../../../libsanitizer/asan/asan_new_delete.cc:151#10x40100finlinked_list::clear()…//此后是詳細的診斷信息,故略去第四章類的高級特性代碼分析鏈表類有兩個以上的構造函數(shù)main中定義了l1和l2兩個對象預期結果兩條構造信息兩條析構信息結果表現(xiàn)出的問題只有一條構造信息只有一條析構信息64.1案例-鏈表類的復制問題4.1.2案例問題分析初始化的情況只有一條構造信息:l2的構造函數(shù)沒有被調用嗎?答案:不可能!因為構造函數(shù)調用是編譯器的強制行為。解釋:顯式定義的構造函數(shù)沒有一個被調用,那么只有一個可能,編譯器自己合成了一個,并且調用了它!第四章類的高級特性分析:那么這個合成的構造函數(shù)的原型是什么?初始化時,用一個已存在的對象去初始化一個正在構建的對象。顯然,這個構造函數(shù)的參數(shù)的類型是這種類本身(的引用)。這種構造函數(shù)稱為“復制構造函數(shù)(copyconstructor)”。合成的復制構造函數(shù)完成了逐成員的復制。這可以理解為源對象的內存復制到目標對象的內存中。74.1案例-鏈表類的復制問題4.1.2案例問題分析初始化的情況第四章類的高級特性合成的復制構造函數(shù)完成了兩個對象的復制。84.1案例-鏈表類的復制問題4.1.2案例問題分析初始化的情況1

2

3

4

5^headtaill1headtaill2復制使兩個對象共享了存儲第四章類的高級特性程序結束時,l2先析構。94.1案例-鏈表類的復制問題4.1.2案例問題分析初始化的情況1

2

3

4

5^headtaill1head:^tail:^l2l2釋放了儲存,導致l1的兩個指針指向了無效地址,成為懸空指針。因此,當l1試圖(再次)釋放內存是就會發(fā)生致命錯誤。第四章類的高級特性代碼分析鏈表類有兩個以上的構造函數(shù)main中定義了l1和l2兩個對象預期結果兩條構造信息兩條析構信息結果表現(xiàn)出的問題有兩條構造信息只有一條析構信息104.1案例-鏈表類的復制問題4.1.2案例問題分析賦值的情況有兩條構造信息:l2被正確構造了。但只有一條析構信息。顯然,其中的一個對象在析構時出錯。出錯的原因與初始化時一樣。第四章類的高級特性常見的復制會發(fā)生在這些場合:對象初始化時linked_listl2{l1};//直接初始化linked_listl3=l1;//復制初始化2.函數(shù)參數(shù):value,notpointer/referencevoidf(linked_listl);linked_listx;f(x);3.函數(shù)返回:value,notpointer/referencelinked_listg(){returnlinked_list({1,2,3});}autoy=g();114.2復制控制4.2.1復制在這些場合中,復制構造函數(shù)起了重要作用。linked_list::linked_list(constlinked_list&l):head(l.head),tail(l.tail),_size(l._size){}//注:第一個參數(shù)實際上可以是本類型任意類型的引用第四章類的高級特性重載的賦值運算符函數(shù)

T&T::operator=(constT&rhs);124.2復制控制4.2.2賦值linked_list&linked_list::operator=(constlinked_list&l){clear();//釋放現(xiàn)有的所有節(jié)點

head=l.head;tail=l.tail_size=l._size;

return*this;//返回對象本身}linked_list(constlinked_list&l):head(l.head),tail(l.tail),_size(l._size){}第四章類的高級特性134.2復制控制4.2.2賦值復制和賦值的異同To1,o2;o2=o1;發(fā)生在賦值(運行)時左操作對象已經存在。它可能已經擁有了資源,需要在賦值時先釋放賦值運算可以級聯(lián)。因此函數(shù)應該返回左操作對象的引用。VS復制賦值To2{o1},o3=o1;發(fā)生在初始化(編譯)時左操作對象正在被構建,不擁有資源復制無需返回任何值第四章類的高級特性144.2復制控制4.2.3淺復制和深復制淺復制已經存在的對象l1資源ra)復制前創(chuàng)建成功的對象l2已經存在的對象l1資源rb)復制后:資源共享正在創(chuàng)建的對象l2沒有資源依然存在的對象l1率先失效的對象l2資源r被l2釋放c)對象l2失效后?第四章類的高級特性154.2復制控制4.2.3淺復制和深復制深復制已經存在的對象l1資源r1a)復制前創(chuàng)建成功的對象l2已經存在的對象l1資源r1b)復制后:資源不共享正在創(chuàng)建的對象l2沒有資源依然存在的對象l1率先失效的對象l2資源r1的副本被釋放c)對象l2失效后資源r1的副本資源r1linked_list::linked_list(constlinked_list&l):head(nullptr),tail(nullptr),_size(0){

for(node_ptrp=l.head;p!=nullptr;p=p->next)push_back(p->data);}第四章類的高級特性164.2復制控制4.2.3淺復制和深復制優(yōu)缺點對比代價較高。需要考慮復制的深度。可能不需要資源共享安全風險較低VS淺復制深復制代價較小可能導致資源共享安全風險較高第四章類的高級特性174.2復制控制4.2.4轉移對象和轉移語義可能的復制路徑classobject{…};objectf(){objectt;

returnt;}//返回局部對象的值autoa=f();復制復制t資源r匿名臨時對象r的副本a資源sr的副本這個過程有問題嗎?第四章類的高級特性184.2復制控制4.2.4轉移對象和轉移語義效率問題復制復制t資源r匿名臨時對象r的副本a資源sr的副本這個對象在復制后失效,資源被釋放這個資源在復制時釋放這個資源是復制而來這正是(早期的)C++被詬病的問題之一。有無好辦法解決這類效率問題呢?第四章類的高級特性194.2復制控制4.2.4轉移對象和轉移語義解決思路復制復制t資源r匿名臨時對象r的副本a資源sr的副本直接“轉移”給a資源s轉移給轉義對象去釋放這類即將失效(expiring)的對象稱為“轉移對象”,用右值引用標記第四章類的高級特性204.2復制控制4.2.4轉移對象和轉移語義編碼實現(xiàn)linked_list&operator=(linked_list&&l){

std::swap(head,l.head);std::swap(tail,l.tail);std::swap(_size,l._size);

return*this;}轉移復制構造函數(shù)轉移賦值運算符函數(shù)linked_list(linked_list&&l):head(l.head),tail(l.tail),_size(l._size){

l.head=l.tail=nullptr;l._size=0;}第四章類的高級特性私有構造函數(shù),但僅聲明,無實現(xiàn)linked_list(constlinked_list&);禁止合成linked_list(constlinked_list&)=delete;linked_list&operator=(constlinked_list&l)=delete;214.2復制控制4.2.5禁止復制第四章類的高級特性概念類型名類名::*指針;類型名(類名::*指針)(參數(shù)列表);初始化指針=&類名::成員名;使用對象.*指針;對象->*指針;224.3指向類成員的指針4.2.5禁止復制第四章類的高級特性初衷僅僅出于效率的考慮。原則一個類的友元可以直接訪問它的所有成員。234.4友元class類名A{

//othermembers;

friend函數(shù)原型聲明;//全局友元函數(shù)聲明

friend類名B::成員函數(shù)原型聲明;//成員函數(shù)友元聲明

friend[class]類名C;//友元類聲明//友元聲明放在哪個段無關緊要};友元特性:非傳遞性非對稱性第四章類的高級特性classX{private:

constinta;//如果沒有初始化,那么只能在構造函數(shù)的初始化列表里進行

constintc=1;//OKintb;

public:X(inti,intj):a(i),b(j){}constintget_c()const{returnc;}};244.5常量和mutable成員4.5.1常量成員第四章類的高級特性classY{public:Y():x(0),y(0){}intx;

mutableinty;};

constYo;o.x=1;//erroro.y=2;//OK254.5常量和mutable成員4.5.2mutable成員第四章類的

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論