拷貝控制函式

2021-08-07 04:06:19 字數 1720 閱讀 2567

拷貝控制包括控制物件的拷貝、移動、賦值和銷毀。類通過定義五種特殊的成員函式來控制這些操作,包括:拷貝建構函式、拷貝賦值運算子、移動建構函式、移動賦值運算子和析構函式。本節主要介紹拷貝建構函式、拷貝賦值運算子和析構函式。

1. 直接初始化與拷貝初始化

什麼是直接初始化,而什麼又是拷貝初始化呢?

簡單點來說,就是定義物件時的寫法不一樣,乙個用括號,如classtest ct1("ab"),而乙個用等號,如classtest ct2 = "ab"。但是從本質來說,它們卻有本質的不同:直接初始化直接呼叫與實參匹配的建構函式,拷貝初始化總是呼叫拷貝建構函式。拷貝初始化首先使用指定建構函式建立乙個臨時物件,然後用拷貝建構函式將那個臨時物件複製到正在建立的物件。所以當拷貝建構函式被宣告為私有時,所有的拷貝初始化都不能使用。

2. 拷貝建構函式

如果乙個函式第乙個引數是自身型別的引用(通常為const引用),且任何額外的引數都有預設值,則為拷貝建構函式。

拷貝建構函式通常用於拷貝初始化,拷貝初始化不僅在我們用=定義變數時會發生,下列情況下也會發生:

a.將乙個物件作為實參傳遞給乙個非引用型別的形參;

b.從乙個返回型別為非引用型別的函式返回乙個物件;

c.用花括號列表初始化乙個陣列中的元素或乙個聚合類中的成員。

拷貝初始化用來初始化非引用型別的形參,這也決定了拷貝建構函式的引數必須是引用型別。如果其引數不是引用型別,則呼叫永遠不會成功----為呼叫拷貝建構函式,我們必須拷貝它的實參,而為了拷貝實參,我們又需要呼叫拷貝建構函式......

有些編譯器可能會對拷貝初始化的過程進行優化,將classtest ct2 = "ab" 優化為classtest ct1("ab"),但即使編譯器略過了拷貝建構函式,該函式也必須

是存在且可以

訪問的(可參考

3.拷貝賦值運算子

拷貝賦值運算子接受乙個與其所在類相同型別的引數,並返回乙個指向其左側運算物件的引用(為保證連續賦值)。

如果你定義乙個空類,編譯器會預設為它宣告乙個預設建構函式,乙個拷貝建構函式,乙個拷貝賦值運算子和乙個析構函式,所有這些函式都是public而且inline的。

拷貝構造運算子通常組合了析構函式和建構函式的操作。類似析構函式,賦值操作會銷毀左側物件的資源,類似拷貝建構函式,賦值操作會從右側運算物件拷貝資料。

但兩項操作必須是以正確的順序執行的,即可以處理自賦值的情況。乙個好的方法是先將右側物件拷貝到區域性變數,然後銷毀左側物件,再將資料從臨時物件拷貝

到左側變 量。

4.析構函式

析構函式執行與建構函式相反的操作,即釋放物件使用的資源,並銷毀物件的非static資料成員。

和建構函式不同,在乙個建構函式中,成員初始化在函式體執行之前完成,且按照它們在類中出現的順序進行初始化。在乙個析構函式中,首先執行函式體,然後銷毀成員,

成員按照初始化順序的逆序銷毀。

通常,析構函式體用來釋放物件在生存期分配的所有資源,銷毀類型別的成員需要執行成員自己的析構函式。

5.三/五法則

a.需要析構函式的類也需要拷貝和賦值操作

合成的析構函式不會delete乙個指標資料成員,因此我們需要自己定義析構函式釋放建構函式分配的記憶體。

若我們為類定義了析構函式,並在析構函式中釋放記憶體,而使用預設版本的拷貝建構函式和賦值運算子就可能發生錯誤。預設拷貝建構函式和賦值運算子會拷貝指標的值,

則兩個物件成員指向相同的位址,在乙個物件被銷毀後,該指標失效,則第二個物件銷毀時會delete乙個無效的指標。

b.需要拷貝操作的類也需要賦值操作,反之亦然

拷貝控制之拷貝建構函式

當我們定義乙個類的時候。我們通常會顯式或隱式的指定在此類的物件在建立 移動 銷毀的時候要做些什麼。乙個類通常通過定義五種特殊的成員函式來控制這些操作 拷貝建構函式 拷貝賦值運算子 移動建構函式 移動賦值運算子 析構函式。如果我們沒有定義這些成員函式,編譯器會自動定義些缺失的操作。有時也會造成些意想不...

c c 拷貝控制 建構函式的問題

問題1 下面 處的 注釋掉後,就編譯不過,為什麼?問題2 但是把 處的也注釋掉後,編譯就過了,為什麼?編譯錯誤 001.cpp in copy constructor test test const test 001.cpp 21 22 error no matching function for ...

C 拷貝控制

本文主要討論c 類定義中的拷貝控制 copy control 拷貝建構函式 賦值操作符和析構函式。如果文中有錯誤或遺漏之處,敬請指出,謝謝!c 類中有四個不可或缺的部分,那就是建構函式 拷貝建構函式 賦值操作符和析構函式。如果類中沒有定義這些函式,那麼編譯器將為類自動生成這些函式。當然,你也可以通過...