最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++中的拷貝構(gòu)造函數(shù)詳解

 更新時間:2022年02月13日 10:28:10   作者:??浦R云  
大家好,本篇文章主要講的是C++中的拷貝構(gòu)造函數(shù)詳解,感興趣的同學(xué)趕快來看一看吧,對你有幫助的話記得收藏一下

C++拷貝構(gòu)造函數(shù)(復(fù)制構(gòu)造函數(shù))詳解

拷貝和復(fù)制是一個意思,對應(yīng)的英文單詞都是copy。對于計算機(jī)來說,拷貝是指用一份原有的、已經(jīng)存在的數(shù)據(jù)創(chuàng)建出一份新的數(shù)據(jù),最終的結(jié)果是多了一份相同的數(shù)據(jù)。例如,將 Word 文檔拷貝到U盤去復(fù)印店打印,將 D 盤的圖片拷貝到桌面以方便瀏覽,將重要的文件上傳到百度網(wǎng)盤以防止丟失等,都是「創(chuàng)建一份新數(shù)據(jù)」的意思。

在 C++ 中,拷貝并沒有脫離它本來的含義,只是將這個含義進(jìn)行了“特化”,是指用已經(jīng)存在的對象創(chuàng)建出一個新的對象。從本質(zhì)上講,對象也是一份數(shù)據(jù),因為它會占用內(nèi)存。

嚴(yán)格來說,對象的創(chuàng)建包括兩個階段,首先要分配內(nèi)存空間,然后再進(jìn)行初始化:

分配內(nèi)存很好理解,就是在堆區(qū)、棧區(qū)或者全局?jǐn)?shù)據(jù)區(qū)留出足夠多的字節(jié)。這個時候的內(nèi)存還比較“原始”,沒有被“教化”,它所包含的數(shù)據(jù)一般是零值或者隨機(jī)值,沒有實際的意義。

初始化就是首次對內(nèi)存賦值,讓它的數(shù)據(jù)有意義。注意是首次賦值,再次賦值不叫初始化。初始化的時候還可以為對象分配其他的資源(打開文件、連接網(wǎng)絡(luò)、動態(tài)分配內(nèi)存等),或者提前進(jìn)行一些計算(根據(jù)價格和數(shù)量計算出總價、根據(jù)長度和寬度計算出矩形的面積等)等。說白了,初始化就是調(diào)用構(gòu)造函數(shù)。

很明顯,這里所說的拷貝是在初始化階段進(jìn)行的,也就是用其它對象的數(shù)據(jù)來初始化新對象的內(nèi)存。

那么,如何用拷貝的方式來初始化一個對象呢?其實這樣的例子比比皆是,string 類就是一個典型的例子。

#include <iostream>
#include <string>
using namespace std;
void func(string str){
    cout<<str<<endl;
}
int main(){
    string s1 = "http://c.ttt.net";
    string s2(s1);
    string s3 = s1;
    string s4 = s1 + " " + s2;
    func(s1);
    cout<<s1<<endl<<s2<<endl<<s3<<endl<<s4<<endl;
   
    return 0;
}
運(yùn)行結(jié)果:
http://c.ttt.net
http://c.ttt.net
http://c.ttt.net
http://c.ttt.net
http://c.ttt.net http://c.ttt.net

s1、s2、s3、s4 以及 func() 的形參 str,都是使用拷貝的方式來初始化的。
對于 s1,表面上看起來是將一個字符串直接賦值給了 s1,實際上在內(nèi)部進(jìn)行了類型轉(zhuǎn)換,將 const char * 類型轉(zhuǎn)換為 string 類型后才賦值的。s4 也是類似的道理。

對于 s1、s2、s3、s4,都是將其它對象的數(shù)據(jù)拷貝給當(dāng)前對象,以完成當(dāng)前對象的初始化。

對于 func() 的形參 str,其實在定義時就為它分配了內(nèi)存,但是此時并沒有初始化,只有等到調(diào)用 func() 時,才會將其它對象的數(shù)據(jù)拷貝給 str 以完成初始化。

當(dāng)以拷貝的方式初始化一個對象時,會調(diào)用一個特殊的構(gòu)造函數(shù),就是拷貝構(gòu)造函數(shù)(Copy Constructor)。

下面的例子演示了拷貝構(gòu)造函數(shù)的定義和使用:

#include <iostream>
#include <string>
using namespace std;
class Student{
public:
    Student(string name = "", int age = 0, float score = 0.0f);  //普通構(gòu)造函數(shù)
    Student(const Student &stu);  //拷貝構(gòu)造函數(shù)(聲明)
public:
    void display();
private:
    string m_name;
    int m_age;
    float m_score;
};
Student::Student(string name, int age, float score): m_name(name), m_age(age), m_score(score){ }
//拷貝構(gòu)造函數(shù)(定義)
Student::Student(const Student &stu){
    this->m_name = stu.m_name;
    this->m_age = stu.m_age;
    this->m_score = stu.m_score;
   
    cout<<"Copy constructor was called."<<endl;
}
void Student::display(){
    cout<<m_name<<"的年齡是"<<m_age<<",成績是"<<m_score<<endl;
}
int main(){
    Student stu1("小明", 16, 90.5);
    Student stu2 = stu1;  //調(diào)用拷貝構(gòu)造函數(shù)
    Student stu3(stu1);  //調(diào)用拷貝構(gòu)造函數(shù)
    stu1.display();
    stu2.display();
    stu3.display();
   
    return 0;
}

運(yùn)行結(jié)果:

Copy constructor was called.
Copy constructor was called.
小明的年齡是16,成績是90.5
小明的年齡是16,成績是90.5
小明的年齡是16,成績是90.5

第 8 行是拷貝構(gòu)造函數(shù)的聲明,第 20 行是拷貝構(gòu)造函數(shù)的定義??截悩?gòu)造函數(shù)只有一個參數(shù),它的類型是當(dāng)前類的引用,而且一般都是 const 引用。

1) 為什么必須是當(dāng)前類的引用呢?

如果拷貝構(gòu)造函數(shù)的參數(shù)不是當(dāng)前類的引用,而是當(dāng)前類的對象,那么在調(diào)用拷貝構(gòu)造函數(shù)時,會將另外一個對象直接傳遞給形參,這本身就是一次拷貝,會再次調(diào)用拷貝構(gòu)造函數(shù),然后又將一個對象直接傳遞給了形參,將繼續(xù)調(diào)用拷貝構(gòu)造函數(shù)……這個過程會一直持續(xù)下去,沒有盡頭,陷入死循環(huán)。

只有當(dāng)參數(shù)是當(dāng)前類的引用時,才不會導(dǎo)致再次調(diào)用拷貝構(gòu)造函數(shù),這不僅是邏輯上的要求,也是 C++ 語法的要求。

2) 為什么是 const 引用呢?

拷貝構(gòu)造函數(shù)的目的是用其它對象的數(shù)據(jù)來初始化當(dāng)前對象,并沒有期望更改其它對象的數(shù)據(jù),添加 const 限制后,這個含義更加明確了。

另外一個原因是,添加 const 限制后,可以將 const 對象和非 const 對象傳遞給形參了,因為非 const 類型可以轉(zhuǎn)換為 const 類型。如果沒有 const 限制,就不能將 const 對象傳遞給形參,因為 const 類型不能轉(zhuǎn)換為非 const 類型,這就意味著,不能使用 const 對象來初始化當(dāng)前對象了。

以上面的 Student 類為例,將 const 去掉后,拷貝構(gòu)造函數(shù)的原型變?yōu)椋?br />Student::Student(Student &stu);

此時,下面的代碼就會發(fā)生錯誤:

const Student stu1("小明", 16, 90.5);
Student stu2 = stu1;
Student stu3(stu1);

stu1 是 const 類型,在初始化 stu2、stu3 時,編譯器希望調(diào)用Student::Student(const Student &stu),但是這個函數(shù)卻不存在,又不能將 const Student 類型轉(zhuǎn)換為 Student 類型去調(diào)用Student::Student(Student &stu),所以最終調(diào)用失敗了。

當(dāng)然,你也可以再添加一個參數(shù)為 const 引用的拷貝構(gòu)造函數(shù),這樣就不會出錯了。換句話說,一個類可以同時存在兩個拷貝構(gòu)造函數(shù),一個函數(shù)的參數(shù)為 const 引用,另一個函數(shù)的參數(shù)為非 const 引用。

默認(rèn)拷貝構(gòu)造函數(shù)

在前面的教程中,我們還沒有講解拷貝構(gòu)造函數(shù),但是卻已經(jīng)在使用拷貝的方式創(chuàng)建對象了,并且也沒有引發(fā)什么錯誤。這是因為,如果程序員沒有顯式地定義拷貝構(gòu)造函數(shù),那么編譯器會自動生成一個默認(rèn)的拷貝構(gòu)造函數(shù)。這個默認(rèn)的拷貝構(gòu)造函數(shù)很簡單,就是使用“老對象”的成員變量對“新對象”的成員變量進(jìn)行一一賦值,和上面 Student 類的拷貝構(gòu)造函數(shù)非常類似。

對于簡單的類,默認(rèn)拷貝構(gòu)造函數(shù)一般是夠用的,我們也沒有必要再顯式地定義一個功能類似的拷貝構(gòu)造函數(shù)。但是當(dāng)類持有其它資源時,如動態(tài)分配的內(nèi)存、打開的文件、指向其他數(shù)據(jù)的指針、網(wǎng)絡(luò)連接等,默認(rèn)拷貝構(gòu)造函數(shù)就不能拷貝這些資源,我們必須顯式地定義拷貝構(gòu)造函數(shù),以完整地拷貝對象的所有數(shù)據(jù)。

總結(jié)

到此這篇關(guān)于C++中的拷貝構(gòu)造函數(shù)詳解的文章就介紹到這了,更多相關(guān)C++拷貝構(gòu)造函數(shù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C++中signed?main和int?main的區(qū)別

    C++中signed?main和int?main的區(qū)別

    這篇文章介紹了C++中signed?main和int?main的區(qū)別,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-12-12
  • C語言數(shù)據(jù)結(jié)構(gòu)之隊列的定義與實現(xiàn)

    C語言數(shù)據(jù)結(jié)構(gòu)之隊列的定義與實現(xiàn)

    隊列是一種特殊的線性表,特殊之處在于它只允許在表的前端(head)進(jìn)行刪除操作,而在表的后端(tail)進(jìn)行插入操作。本文將詳細(xì)講講C語言中隊列的定義與實現(xiàn),感興趣的可以了解一下
    2022-07-07
  • C語言手把手教你實現(xiàn)貪吃蛇AI(上)

    C語言手把手教你實現(xiàn)貪吃蛇AI(上)

    這篇文章主要介紹了C語言手把手教你實現(xiàn)貪吃蛇AI,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-01-01
  • C語言每日練習(xí)之選擇排序

    C語言每日練習(xí)之選擇排序

    本篇文章主要介紹了 C語言的選擇排序,這里提供代碼實例以便大家理解,通過本文,更好的理解排序算法
    2021-11-11
  • 詳解C++文件讀寫操作

    詳解C++文件讀寫操作

    這篇文章主要為大家詳細(xì)介紹了C++文件讀寫操作,感興趣的小伙伴們可以參考一下
    2016-03-03
  • C語言實現(xiàn)簡單井字棋游戲

    C語言實現(xiàn)簡單井字棋游戲

    這篇文章主要為大家詳細(xì)介紹了C語言實現(xiàn)簡單井字棋游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-04-04
  • 深入理解atoi()與itoa()函數(shù)的用法

    深入理解atoi()與itoa()函數(shù)的用法

    本篇文章是對atoi()與itoa()函數(shù)的用法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • 詳解C語言中的預(yù)處理命令

    詳解C語言中的預(yù)處理命令

    初學(xué)C語言的時候,我們會在開頭寫下一句話,#include<stdio.h>,這就是預(yù)處理命令,下面我們通過這篇文章來了解一下,感興趣的可以跟隨小編一起學(xué)習(xí)一下
    2022-12-12
  • C語言深入分析函數(shù)與宏的使用

    C語言深入分析函數(shù)與宏的使用

    C語言函數(shù)是一種函數(shù),用來編譯C語言,一般包括字符庫函數(shù),數(shù)學(xué)函數(shù),目錄函數(shù),進(jìn)程函數(shù),診斷函數(shù),操作函數(shù)等,宏在C語言中是一段有名稱的代碼片段。無論何時使用到這個宏的時候,宏的內(nèi)容都會被這段代碼替換掉
    2022-04-04
  • C++虛函數(shù)表深入研究

    C++虛函數(shù)表深入研究

    這篇文章主要介紹了C++的虛函數(shù)表,內(nèi)容非常詳細(xì),思路清晰,需要的朋友可以參考下,希望能夠給你帶來幫助
    2021-10-10

最新評論

航空| 荔波县| 乌鲁木齐县| 明光市| 浮山县| 大渡口区| 翁源县| 洪洞县| 大冶市| 双鸭山市| 剑川县| 邓州市| 施秉县| 宁安市| 宾阳县| 天祝| 沾化县| 澄江县| 宜丰县| 玛曲县| 含山县| 云南省| 临海市| 六盘水市| 富川| 南昌县| 柳江县| 威远县| 临潭县| 太谷县| 武安市| 杨浦区| 铅山县| 龙川县| 舞阳县| 平度市| 吉林省| 安泽县| 湄潭县| 闸北区| 铁力市|