C++中拷貝構(gòu)造函數(shù)的總結(jié)詳解
1.什么是拷貝構(gòu)造函數(shù):
拷貝構(gòu)造函數(shù)嘛,當(dāng)然就是拷貝和構(gòu)造了。(其實(shí)很多名字,只要靜下心來(lái)想一想,就真的是顧名思義呀)拷貝又稱復(fù)制,因此拷貝構(gòu)造函數(shù)又稱復(fù)制構(gòu)造函數(shù)。百度百科上是這樣說(shuō)的:拷貝構(gòu)造函數(shù),是一種特殊的構(gòu)造函數(shù),它由編譯器調(diào)用來(lái)完成一些基于同一類的其他對(duì)象的構(gòu)建及初始化。其唯一的參數(shù)(對(duì)象的引用)是不可變的(const類型)。此函數(shù)經(jīng)常用在函數(shù)調(diào)用時(shí)用戶定義類型的值傳遞及返回。
2.拷貝構(gòu)造函數(shù)的形式
Class X
{
public:
X();
X(const X&);//拷貝構(gòu)造函數(shù)
}
2.1為什么拷貝構(gòu)造參數(shù)是引用類型?
其原因如下:當(dāng)一個(gè)對(duì)象以傳遞值的方式傳一個(gè)函數(shù)的時(shí)候,拷貝構(gòu)造函數(shù)自動(dòng)被調(diào)用來(lái)生成函數(shù)中的對(duì)象(符合拷貝構(gòu)造函數(shù)調(diào)用的情況)。如果一個(gè)對(duì)象是被傳入自己的拷貝構(gòu)造函數(shù),它的拷貝構(gòu)造函數(shù)將會(huì)被調(diào)用來(lái)拷貝這個(gè)對(duì)象,這樣復(fù)制才可以傳入它自己的拷貝構(gòu)造函數(shù),這會(huì)導(dǎo)致無(wú)限循環(huán)直至棧溢出(Stack Overflow)。
3.拷貝構(gòu)造函數(shù)調(diào)用的三種形式
3.1.一個(gè)對(duì)象作為函數(shù)參數(shù),以值傳遞的方式傳入函數(shù)體;
3.2.一個(gè)對(duì)象作為函數(shù)返回值,以值傳遞的方式從函數(shù)返回;
3.3.一個(gè)對(duì)象用于給另外一個(gè)對(duì)象進(jìn)行初始化(常稱為復(fù)制初始化)。
總結(jié):當(dāng)某對(duì)象是按值傳遞時(shí)(無(wú)論是作為函數(shù)參數(shù),還是作為函數(shù)返回值),編譯器都會(huì)先建立一個(gè)此對(duì)象的臨時(shí)拷貝,而在建立該臨時(shí)拷貝時(shí)就會(huì)調(diào)用類的拷貝構(gòu)造函數(shù)。
4.深拷貝和淺拷貝
如果在類中沒(méi)有顯式地聲明一個(gè)拷貝構(gòu)造函數(shù),那么,編譯器將會(huì)自動(dòng)生成一個(gè)默認(rèn)的拷貝構(gòu)造函數(shù),該構(gòu)造函數(shù)完成對(duì)象之間的位拷貝。(位拷貝又稱淺拷貝,后面將進(jìn)行說(shuō)明。)自定義拷貝構(gòu)造函數(shù)是一種良好的編程風(fēng)格,它可以阻止編譯器形成默認(rèn)的拷貝構(gòu)造函數(shù),提高源碼效率。
在某些狀況下,類內(nèi)成員變量需要?jiǎng)討B(tài)開辟堆內(nèi)存,如果實(shí)行位拷貝,也就是把對(duì)象里的值完全復(fù)制給另一個(gè)對(duì)象,如A=B。這時(shí),如果B中有一個(gè)成員變量指針已經(jīng)申請(qǐng)了內(nèi)存,那A中的那個(gè)成員變量也指向同一塊內(nèi)存。這就出現(xiàn)了問(wèn)題:當(dāng)B把內(nèi)存釋放了(如:析構(gòu)),這時(shí)A內(nèi)的指針就是野指針了,出現(xiàn)運(yùn)行錯(cuò)誤。事實(shí)上這就要用到深拷貝了,要自定義拷貝構(gòu)造函數(shù)。
深拷貝和淺拷貝可以簡(jiǎn)單理解為:如果一個(gè)類擁有資源,當(dāng)這個(gè)類的對(duì)象發(fā)生復(fù)制過(guò)程的時(shí)候,資源重新分配,這個(gè)過(guò)程就是深拷貝,反之,沒(méi)有重新分配資源,就是淺拷貝。
下面舉個(gè)深拷貝的例子。
#include <iostream>
using namespace std;
class CA
{
public:
CA(int b,char* cstr)
{
a=b;
str=new char[b];
strcpy(str,cstr);
}
CA(const CA& C)
{
a=C.a;
str=new char[a]; //深拷貝
if(str!=0)
strcpy(str,C.str);
}
void Show()
{
cout<<str<<endl;
}
~CA()
{
delete str;
}
private:
int a;
char *str;
};
int main()
{
CA A(10,"Hello!");
CA B=A;
B.Show();
return 0;
}
淺拷貝資源后在釋放資源的時(shí)候會(huì)產(chǎn)生資源歸屬不清的情況導(dǎo)致程序運(yùn)行出錯(cuò)。一定要注意類中是否存在指針成員。
5.拷貝構(gòu)造函數(shù)與“=“賦值運(yùn)算符
例如:
class CExample
{};
int main()
{
CExample e1 = new CExample;
CExample e2 = e1;//調(diào)用拷貝構(gòu)造函數(shù)
CExample e3(e1);//調(diào)用拷貝構(gòu)造函數(shù)
CExample e4;
e4 = e1;//調(diào)用=賦值運(yùn)算符
}
通常的原則是:①對(duì)于凡是包含動(dòng)態(tài)分配成員或包含指針成員的類都應(yīng)該提供拷貝構(gòu)造函數(shù);②在提供拷貝構(gòu)造函數(shù)的同時(shí),還應(yīng)該考慮重載"="賦值操作符號(hào)。
- C++類成員構(gòu)造函數(shù)和析構(gòu)函數(shù)順序示例詳細(xì)講解
- 深入解析C++中的構(gòu)造函數(shù)和析構(gòu)函數(shù)
- c++類構(gòu)造函數(shù)詳解
- 深入C++中構(gòu)造函數(shù)、拷貝構(gòu)造函數(shù)、賦值操作符、析構(gòu)函數(shù)的調(diào)用過(guò)程總結(jié)
- c++中拷貝構(gòu)造函數(shù)的參數(shù)類型必須是引用
- 解析C++中構(gòu)造函數(shù)的默認(rèn)參數(shù)和構(gòu)造函數(shù)的重載
- C++中拷貝構(gòu)造函數(shù)的應(yīng)用詳解
- C++11委托構(gòu)造函數(shù)和繼承構(gòu)造函數(shù)的實(shí)現(xiàn)
相關(guān)文章
C語(yǔ)言實(shí)現(xiàn)餐飲管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)餐飲管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03C/C++使用fmt庫(kù)實(shí)現(xiàn)格式化字符串
fmt庫(kù)是一個(gè)高效、易用的C++格式化庫(kù),可以幫助我們方便地進(jìn)行字符串格式化、輸出、日志記錄等操作,下面我們就來(lái)學(xué)習(xí)一下fmt格式化字符串的具體操作吧2023-12-12C/C++內(nèi)存管理之new與delete的使用及原理解析
這篇文章主要介紹了C/C++內(nèi)存管理之new與delete的使用及原理解析,本文通過(guò)實(shí)例代碼圖文相結(jié)合給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧2024-08-08C語(yǔ)言柔性數(shù)組的實(shí)現(xiàn)示例
柔性數(shù)組既數(shù)組大小待定的數(shù)組, C語(yǔ)言中結(jié)構(gòu)體的最后一個(gè)元素可以是大小未知的數(shù)組,本文就來(lái)介紹一下柔性數(shù)組的用法,感興趣的可以了解一下2024-03-03