2019.6.14 c++拷貝建構函式詳解
一、什麼是拷貝建構函式
首先對於普通型別的物件來說,他們之間的複製是很簡單的,例如:
int a = 100;
int b = a;
而類物件與普通物件不同,類物件內部結構一般較為複雜,存在各種成員變數。
下面看乙個類物件拷貝的簡單例子。
#includeusing namespace std;
class cexample
//拷貝建構函式
cexample(const cexample & c)
//析構函式
~cexample()
void show()
cexample(const cexample & c)
~cexample()
void show()
//拷貝建構函式
cexample(const cexample & c)
//析構函式
~cexample()
void show()
#includeusing namespace std;
class rect
~rect()
static int getcount()
private:
int width;
int height;
static int count;
};int rect::count=0;
int main()
rect(const rect& r)
~rect()
static int getcount()
private:
int width;
int height;
static int count;
};int rect::count=0;
int main()
, 如果呼叫foo(obj); 首先class_type obj_local(obj) ,這樣就定義了區域性變數obj_local供函式內部使用
ii)引用傳遞:
無論對內建型別還是類型別,傳遞引用或指標最終都是傳遞的位址值!而位址總是指標型別(屬於簡單型別), 顯然引數傳遞時,按簡單型別的賦值拷貝,而不會有拷貝建構函式的呼叫(對於類型別).
4. 在類中有指標資料成員時,拷貝建構函式的使用?
如果不顯式宣告拷貝建構函式的時候,編譯器也會生成乙個預設的拷貝建構函式,而且在一般的情況下執行的也很好。但是在遇到類有指標資料成員時就出現問題 了:因為預設的拷貝建構函式是按成員拷貝構造,這導致了兩個不同的指標(如ptr1=ptr2)指向了相同的記憶體。當乙個例項銷毀時,呼叫析構函式 free(ptr1)釋放了這段記憶體,那麼剩下的乙個例項的指標ptr2就無效了,在被銷毀的時候free(ptr2)就會出現錯誤了, 這相當於重複釋放一塊記憶體兩次。這種情況必須顯式宣告並實現自己的拷貝建構函式,來為新的例項的指標分配新的記憶體。
問題1和2回答了為什麼拷貝建構函式使用值傳遞會產生無限遞迴呼叫的問題;
問題3回答了回答了在類中有指標資料成員時,拷貝建構函式使用值傳遞等於白顯式定義了拷貝建構函式,因為預設的拷貝建構函式就是這麼幹的。
5. 拷貝建構函式裡能呼叫private成員變數嗎?
解答:這個問題是在網上見的,當時一下子有點暈。其時從名子我們就知道拷貝建構函式其時就是乙個特殊的建構函式,操作的還是自己類的成員變數,所以不受private的限制。
6. 以下函式哪個是拷貝建構函式,為什麼?
x::x(const x&); //拷貝建構函式
x::x(x);
x::x(x&, int a = 1); //拷貝建構函式
x::x(x&, int a = 1, int b = 2); //拷貝建構函式
解答:對於乙個類x, 如果乙個建構函式的第乙個引數是下列之一:
a) x&
b) const x&
c) volatile x&
d) const volatile x&
且沒有其他引數或其他引數都有預設值,那麼這個函式是拷貝建構函式.
7. 乙個類中可以存在多於乙個的拷貝建構函式嗎?
解答:類中可以存在超過乙個拷貝建構函式。
class x
注意,如果乙個類中只存在乙個引數為 x& 的拷貝建構函式,那麼就不能使用const x或volatile x的物件實行拷貝初始化.
如果乙個類中沒有定義拷貝建構函式,那麼編譯器會自動產生乙個預設的拷貝建構函式。
這個預設的引數可能為 x::x(const x&)或 x::x(x&),由編譯器根據上下文決定選擇哪乙個。
五、c++建構函式以及析構函式的若干面試問題
q1:建構函式能否過載,析構函式能否過載,為什麼?
a1:建構函式可以,析構函式不可以。
q2:析構函式為什麼一般情況下要宣告為虛函式?
a2:虛函式是實現多型的基礎,當我們通過基類的指標是析構子類物件時候,如果不定義成虛函式,那只呼叫基類的析構函式,子類的析構函式將不會被呼叫。如 果定義為虛函式,則子類父類的析構函式都會被呼叫。
q3:什麼情況下必須定義拷貝建構函式?
a3:當類的物件用於函式值傳遞時(值引數,返回類物件),拷貝建構函式會被呼叫。如果物件複製並非簡單的值拷貝,那就必須定義拷貝建構函式。例如大的堆 棧資料拷貝。如果定義了拷貝建構函式,那也必須過載賦值操作符。
參考部落格:
C 拷貝建構函式 深拷貝,淺拷貝
對於普通型別的物件來說,它們之間的複製是很簡單的,例如 int a 88 int b a 而類物件與普通物件不同,類物件內部結構一般較為複雜,存在各種成員變數。下面看乙個類物件拷貝的簡單例子。執行程式,螢幕輸出100。從以上 的執行結果可以看出,系統為物件b分配了記憶體並完成了與物件a的複製過程。就...
C 拷貝建構函式 深拷貝,淺拷貝
對於普通型別的物件來說,它們之間的複製是很簡單的,例如 int a 88 int b a 而類物件與普通物件不同,類物件內部結構一般較為複雜,存在各種成員變數。下面看乙個類物件拷貝的簡單例子。include using namespace std class cexample void show 執...
C 拷貝建構函式 深拷貝,淺拷貝
c 拷貝建構函式 深拷貝,淺拷貝 對於普通型別的物件來說,它們之間的複製是很簡單的,例如 int a 88 int b a 而類物件與普通物件不同,類物件內部結構一般較為複雜,存在各種成員變數。下面看乙個類物件拷貝的簡單例子。iostream using namespace std class ce...