1:知識點1:在定義一個類時,我們可以顯式或隱式的定義在此類型的對象拷貝、賦值、移動、銷毀是做什么,主要通過五種特殊的成員函數來完成這些操作:拷貝構造函數、拷貝復制運算符、移動構造函數、移動復制運算符。析構函數
知識點2:拷貝和移動構造函數定義了當用同類型的一個對象初始化本對象時做什么??截惡鸵苿淤x值運算符定義了將一個對象賦予同類型的另一個對象時做什么。析構函數定義了當此類型對象銷毀時的操作
知識點3:若一個類沒有顯式的定義這五個操作,編譯器會自動為其定義缺失的操作,在定義一個類時,拷貝控制操作是非常的重要的
知識點4:拷貝構造函數:本身是一個構造函數,其參數是一個自身類類型的引用,且任何額外參數皆有默認值
知識點5:每個成員的類型決定了它的拷貝方式,對于類類型,將調用其拷貝構造函數進行拷貝,對于內置類型,則會直接拷貝,對于數組的拷貝是逐個元素的拷貝,若數組的元素是類類型,則使用拷貝構造函數來拷貝
知識點6:直接初始化:一對小括號加參數??截惓跏蓟旱忍栍覀葘ο罂截惖秸趧摻ǖ膶ο笾?,如果需要還需進行類型轉換(拷貝初始化沒有=號的情況:將一個對象作為實參傳遞給一個非引用類型的形參時、從一個返回類型非引用類型的函數返回一個對象、用花括號初始化列表初始化一個數組的元素或一個聚合類的成員)
知識點7:函數的調用中,非引用類型的參數都要進行拷貝初始化。非引用類型的返回值也會被用來初始化調用方的結果
見知識點
2:此為一個類的拷貝構造函數,作為函數其非引用類型的參數需要進行拷貝初始化,但拷貝初始化又要調用拷貝構造函數以拷貝實參,但為了拷貝實參又需要調用拷貝構造函數,無限循環。
3:StrBlob中元素復制,且智能指針計數加一。StrBlobStr中元素復制,弱指針復制不影響計數器
4:首先foo_bar函數的參數為非引用類型,需拷貝,使用拷貝構造函數、函數的返回類型非引用,也需要進行拷貝,使用拷貝構造函數。
在函數體中arg拷貝到local對象,global拷貝到heap對象,local、*heap拷貝到pa[4]中皆使用拷貝構造函數
local拷貝到*heap為拷貝賦值運算符
5:
Hasptr(const Hasptr& HP):*ps(new string *HP.ps),i(HP.i){}6:知識點1:拷貝復制運算符,其實就是一個名為 Operator= 的函數(operator后加表示要定義的運算符的符號),重載運算符,有返回類型和參數,返回類型通常是左側運算符的引用
知識點2:若在類內未顯式定義,則編譯器會自動生成合成拷貝賦值運算符,它主要是將運算符右側的所有非static成員賦給左側元算對象對應成員(或是用來禁止該類型對象的賦值)
見知識點
7:所有成員的賦值會發生,兩個StrBlob中智能指針所指對象內存相同,計數器加一,兩個StrBlobPtr中弱指針所致對象內存相同,計數器不變。
8:相較于第五題,將賦值過程置于函數體內,而不是初始化列表,返回類型不同
HasPtr& operator= (const Hasptr& HP){ string *p = new string(*HP.ps);//new返回的是指向分配好內存、創建了對象的指針 delete ps;//首先刪除原內存 ps = p; //賦值 i = HP.i; return *this;//返回值}9:知識點1:構造函數初始化對象的非static數據成員,析構函數釋放對象所使用資源,并銷毀對象的非static數據成員
知識點2:形式:波浪號加類名
知識點3:構造函數中,成員初始化是在函數體執行之前完成的,且按照他們在類內出現的順序進行初始化,析構函數中,首先執行函數體,然后銷毀成員,成員按照初始化順序的逆序銷毀,所以析構函數可以執行設計者想要的任何收尾工作,再銷毀成員
知識點4:成員的銷毀完全依賴于其本身的類型,類類型需要執行自身的析構函數,而內置類型則什么也不做(無析構函數)
知識點5:調用析構函數的情況:
1:變量離開作用域時被銷毀
2:當對象被銷毀,其成員被銷毀
3:容器被銷毀,成員被銷毀
4:動態分配的對象,指針被delete時
5:臨時對象,創建的完整表達式結束時
知識點6:合成析構函數—編譯器自動生成的析構函數,基本上為空,或者被用來阻止對象被銷毀
知識點7:析構函數體自身并不直接銷毀成員,是在析構函數體執行完畢之后隱式的析構階段中被銷毀的
見知識點
10:所有對象的數據成員被銷毀,智能指針的計數減一,所有對象的數據成員被銷毀,弱指針不影響計數器
新聞熱點
疑難解答
圖片精選