C 拷貝控制

2021-05-25 02:12:18 字數 2245 閱讀 5875

本文主要討論c++類定義中的拷貝控制(copy control):拷貝建構函式、賦值操作符和析構函式。

如果文中有錯誤或遺漏之處,敬請指出,謝謝!

c++類中有四個不可或缺的部分,那就是建構函式、拷貝建構函式、賦值操作符和析構函式。如果類中沒有定義這些函式,那麼編譯器將為類自動生成這些函式。當然,你也可以通過private控制策略限定不使用拷貝建構函式和賦值操作符。

其中,拷貝建構函式、賦值操作符和析構函式總稱為拷貝控制(copy control)。

當類中有指標類資料成員時,一般都需要自已實現類的拷貝控制。通常有兩種處理策略:一是定義值型類,每個類保留乙份指標指向的物件的拷貝;另一種更常用的策略是使用智慧型指標(smart pointer),其通用技術是採用引用計數(reference count)來實現共享指標指向的物件。

拷貝建構函式

我們知道c++中變數初始化有兩種形式:直接初始化和拷貝初始化。直接初始化將初始化放在圓括號中,而拷貝初始化使用=符號。對於內建型別,這兩者基本上沒有區別。但對於類型別,兩種方式是有區別的:直接初始化直接呼叫與實參匹配的建構函式;而拷貝初始化總是呼叫拷貝建構函式,具體而言,就是拷貝初始化首先使用指定建構函式建立乙個臨時物件,然後用拷貝建構函式將那個臨時物件拷貝到正在建立的物件。

支援拷貝初始化主要是為了與c的用法相容。當情況允許時,可以允許編譯器跳過拷貝建構函式直接建立物件,但編譯器沒有義務這樣做。注:事實上大多數編譯器都跳過了拷貝建構函式,因為這完全可以跳過,比如在vc6.0和mingw2.05。

我們知道可以用表示容量的單個引數來初始化容器,容器的這種構造方式使用了預設建構函式和拷貝建構函式。例如:

vectorsvec(5);

編譯器首先使用string的預設建構函式建立乙個臨時值來初始化svec,然後使用拷貝建構函式將臨時物件拷貝到svec的每個元素。示例**如下:

#

include

<

iostream

>

#include

<

vector

>

using

namespace

std;

class

test

test

(const

test

& t)};

int main(

)

輸出結果為:(mingw 2.05和vc6.0)

contructor

copy contructor

copy contructor

copy contructor

copy contructor

copy contructor

對於元素為類型別的陣列,可以使用陣列初始化列表來提供顯示元素初始化。此時,使用拷貝初始化來初始化每個元素。根據指定值建立適當型別的元素,然後用拷貝建構函式將該值拷貝到相應元素。當然,同前面一樣,是否跳過拷貝建構函式取決於編譯器(事實上,大多數編譯器跳過了這步)。

拷貝建構函式的形參是乙個類型別引用(否則,引數本身就需要過拷貝建構函式了),但一般情況下,我們使用const修飾。並且,一般不應該設定為explicit。

有時需要禁止拷貝類,例如,iostream類就不允許拷貝。這時,應當顯示宣告拷貝建構函式為private,此時可以不定義該函式。若宣告為private且進行了函式定義,則類的友元和成員仍然可以進行拷貝。

注意:宣告而不定義成員函式是合法的,但是,使用未定義成員的任何嘗試將導致鏈結失敗。

合成的拷貝建構函式

如果我們沒有定義拷貝建構函式,則編譯器會自動生成乙個,把這個自動生成的拷貝建構函式叫合成的拷貝建構函式(synthesized copy constructor)。合成的拷貝建構函式執行逐個成員初始化,將新物件初始化為原物件的副本。如果成員是內建型別,則執行位拷貝;如果成員是類型別,則呼叫相應的拷貝建構函式;如果成員是陣列型別,則分別對每個陣列元素進製拷貝。

賦值操作符

賦值操作符的右運算元一般以const引用傳遞,為了與內建型別的行為一致,常返回該類型別的引用。通常,拷貝建構函式和賦值操作符是同時出現的,定義了乙個就應當定義另乙個。

賦值操作符乙個必須小心的地方時檢查自賦值。

析構函式

三法則(rule of three):如果類需要自定義析構函式,則它往往也需要拷貝建構函式和賦值操作符。

合成的析構函式按成員在類中宣告次序的逆序來撤銷成員。

析構函式與拷貝建構函式或者賦值操作符之間的乙個重要區別是:即使我們編寫了自己的析構函式,在自定義析構函式執行結束後,合成析構函式仍然將繼續執行,它來完成成員資料的撤銷工作。

C 拷貝控制

當定義乙個類時,顯示或隱式地指定了此型別的物件在拷貝 賦值和銷毀時所執行的操作,通過三個特殊的成員函式來控制這些操作,分別是拷貝建構函式,賦值運算子和析構函式。拷貝建構函式定義了當使用同型別的另乙個物件初始化新物件時的操作,賦值運算子定義了將乙個物件賦值給同型別的另乙個物件時的操作,析構函式定義了此...

C 拷貝控制

拷貝建構函式 如果有乙個建構函式第乙個引數是自身類型別的引用,且任何額外引數都有預設值,則此建構函式是拷貝建構函式。class foo 如果沒有為乙個類定義拷貝建構函式,編譯器會為我們定義乙個。拷貝建構函式不僅在我們用 定義變數時發生,也會在一下情況發生 拷貝賦值運算子 與拷貝建構函式一樣,如果類未...

C 拷貝控制

c 作為高階語言,物件導向程式設計是其重要的語言特性。設計好的架構,其基礎也是類的設計。我們之前已經將類本身的知識梳理了一遍。這一章著重介紹類控制,包括拷貝控制 過載 物件導向設計以及模板和泛型程式設計。這些非常非常重要,是實現工程必須要掌握的基礎知識。要打起十分的精神來學習。按照c primer的...