什麼時候會用到拷貝建構函式?

2021-04-08 15:54:05 字數 3261 閱讀 2647

1-什麼時候會用到拷貝建構函式? 

2-什麼時候有必要手動寫拷貝建構函式?

1-什麼時候會用到拷貝建構函式?

當任何你想影印東西的時候,而不管東西被影印成什麼樣子。即任何你想利用乙個已有的類例項給另乙個類例項賦值時,這種賦值可能是顯式的,也可能是隱式的

顯式:classa_1=class_2;

隱式:函式的形參有用到類物件卻沒有用引用或傳址技術時

函式的返回值是乙個物件也沒有應用傳址技術時

2-什麼時候有必要用拷貝建構函式?

上述3種情況,如果沒有涉及到深拷貝問題,就沒有必要自己來編寫拷貝建構函式,編譯器有預設的可以很完美的完成任務

還一種情況就是**的拷貝:在拷內過程中進行縮放,放大等處理,不過沒什麼用

//關於深拷貝 以下是引用:traceback:http://www.netology.cn/blog/user1/bachelor/archives/2006/375.html

關於深拷貝

如果乙個類中含有指標成員變數,則在利用乙個已存在物件構造新的物件時,就會面臨兩種選擇:深拷貝和淺拷貝。

淺拷貝只是將物件間對應的指標成員變數進行簡單的拷貝,即拷貝結束後新舊物件的指標指向相同的資源(指標的值是相同的);這種拷貝會導致物件的成員不可用,如下例:

class person

~person()

}//....

char * place = new char [20];

strcpy(place,"china");

person *a = new person();

a->sethome(place);

person * b= person(a);

delete a;

//....

此時物件a 和物件b的成員home值相同,如果a物件 destroy,則物件b的成員home指向的位址變為不可用(物件a撤銷時將home指向的資源釋放了)。

深拷貝是相對於淺拷貝而言的,為了避免上述情況的發生,將上例中的**改造:物件拷貝時將指標指向的內容拷貝,**如下:

class person

person & person(const person & per)

~person()

}深拷貝之後,新舊物件的home成員指向的內容的值相同,而其自身的值不同。這樣就可避免出現其中之一

destroy 之後,另一物件的home成員不可用。

但是,此種開闢新的記憶體區域然後賦值拷貝的方法在面臨指標成員指向的資料量很大時出現效率低下的問題,因此又有下面的處理方法:為指標保留引用計數(reference counting)。

當類每次拷貝這個指標時,就增加它的計數;物件destroy時檢察指標的引用計數,如果為0就刪除其指向的資源,否則計數減小。如果指標所指資料相對恆定是,指標引用計數尤為有效。而且在資料量龐大的時候,可以有較高的執行效率。

類示例**如下:

//乙個引用計數器很容易作為乙個類來完成

//用於帶乙個引用計數值得void指標的類

class voidrefptr

//increment the reference count

voidrefptr * ref()

//decrement the count and delete if zero

void derf()

~voidrefptr()

void * ptr()

private:

void * ptr;//the data

unsigned int ncount;//the reference count

};//這個類包含了乙個實際的指標和用於對引用計數器自加自減的成員函式

//當引用計數器減到零時,物件撤銷自身。

class refcountcharptr

refcountcharptr(const refcountcharptr &a)

~refcountcharptr()

const refcountcharptr & operator = (const refcountcharptr & a)

refcountcharptr & operator =(const char * pdata)

//type conversion to a char string

operator const char * ()

protected:

private:

voidrefptr * pref;

};乙個同學給出了乙個類似的實現:

class refdata

int refcount;

string *data;

};class mystring

;mystring::mystring(const char *s = ""):value(new refdata(s))

mystring & mystring::operator=(const mystring & str)

char & mystring::operator(int dex) //改變值的時候

return value->data[index];

}//測試示例

int main()

雖然引用計數的處理方法貌似不錯,但是其亦存在其弊端:在多執行緒的條件下,其執行效率尤為低下。具體參見(herb shutter的在c++ report雜誌中的guru專欄以及整理後出版的《more exceptional c++》中專門的討論)。

最近在看設計模式的一些東東,偶然又發現了下面的一段:

下面是一些可以使用proxy模式的常見情況:

...4)智慧型指引(**art reference)--取代了簡單的指標,它在訪問物件時執行一些附加操作。它的典型用途包括:

對指向實際物件的引用計數,這樣當該物件沒有引用時,可以自動釋放它(也稱為 **artpointers[ede92]).

當第一次引用乙個持久物件時,將它裝入記憶體。

在訪問乙個實際物件前,檢察是否已經鎖定了它,以確保其他物件不能改變它。

以上的敘述的用途好像有些像引用計數,但是具體如何,現在偶還不是很清楚,準備將兩者放在一起,看其聯絡和區別究竟如何。

以上只是最近在看c++時遇到的一點問題,將其放在一起討論,希望可以明白其原理和實現。

參考文章:

什麼時候會用到拷貝建構函式?

摘自 1 什麼時候會用到拷貝建構函式?2 什麼時候有必要手動寫拷貝建構函式?1 什麼時候會用到拷貝建構函式?當任何你想影印東西的時候,而不管東西被影印成什麼樣子。即任何你想利用乙個已有的類例項給另乙個類例項賦值時,這種賦值可能是顯式的,也可能是隱式的 顯式 classa 1 class 2 隱式 函...

什麼時候呼叫拷貝建構函式

以下幾種情況會呼叫拷貝建構函式 1.以乙個物件初始化另乙個物件 2.函式以某個物件為引數 3.函式返回某個物件 4.初始化序列式容器的元素 2.void test2 另外以下程式 points i pointsarray1.points i 這一行並不會觸發 拷貝建構函式。呼叫的是 賦值運算子。賦值...

什麼時候呼叫複製建構函式(拷貝建構函式)

原文 slyar home www.slyar.com 這個問題不是疑問了,查了一下國外 總結一下。假設person是乙個類,複製建構函式的呼叫會在以下幾種情況下發生 1 物件在建立時使用其他的物件初始化 person p q 此時複製建構函式被用來建立例項p person p q 此時複製建構函式...