亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C++ > 正文

C++教程:C++拷貝構造函數

2020-05-23 14:25:55
字體:
來源:轉載
供稿:網友
我們在程序中常常需要把一些數據復制一份出來備作它用。對于只有基本類型變量的程序來說,這是輕而易舉就能做到的——新建一個臨時變量,用一句賦值語句就能完成。但如果它是一個有著許許多多成員數據的對象,這就會非常麻煩。最要命的是,那些成員數據還是私有的,根本無法直接訪問或修改。那么這時候,我們怎么“克隆”出一個和原來的對象相同的新對象呢?

拷貝構造函數

我們知道,構造函數是可以帶上參數的,這些參數可以是整型、字符型等等,那么它可不可以是一個對象類型呢?我們把一個原來的對象丟給構造函數,然后讓它給我們造一個相同的對象,是否可以呢?下面我們就來試試看:(程序15.4.1)
//node.h
#include <iostream>
using namespace std;
class Node//定義一個鏈表結點類
{
   public:
   Node();//構造函數的聲明
   Node(int i,char c='0');//構造函數重載1
   Node(int i,char c,Node *p,Node *n);//構造函數重載2
   Node(Node &n);//結點拷貝構造函數,&表示引用
   int readi() const;//讀取idata
   char readc() const;//讀取cdata
   Node * readp() const;//讀取上一個結點的位置
   Node * readn() const;//讀取下一個結點的位置
   bool set(int i);//重載,通過該函數修改idata
  bool set(char c);//重載,通過該函數修改cdata
   bool setp(Node *p);//通過該函數設置前驅結點
   bool setn(Node *n);//通過該函數設置后繼結點
   private:
   int idata;//存儲數據保密
   char cdata;//存儲數據保密
   Node *prior;//前驅結點的存儲位置保密
   Node *next;//后繼結點的存儲位置保密
};
//未定義的函數與程序15.2.2相同
Node::Node(Node &n)
{
   idata=n.idata;//可以讀出同類對象的私有成員數據
   cdata=n.cdata;
   prior=n.prior;
   next=n.next; 
}
//linklist.h
#include "node.h"//需要使用鏈表結點類
#include <iostream>
using namespace std;
class Linklist
{
   public:
   Linklist(int i,char c);//鏈表類構造函數
   Linklist(Linklist &l);//鏈表拷貝構造函數,&表示引用
   bool Locate(int i);//根據整數查找結點
   bool Locate(char c);//根據字符查找結點
   bool Insert(int i=0,char c='0');//在當前結點之后插入結點
   bool Delete();//刪除當前結點
   void Show();//顯示鏈表所有數據
   void Destroy();//清除整個鏈表
   private:
   Node head;//頭結點
   Node * pcurrent;//當前結點指針
};
//未定義的函數與程序15.3相同
Linklist::Linklist(Linklist &l):head(l.head)//調用結點的拷貝構造函數來初始化head
{
   cout<<"Linklist cloner running..." <<endl;
   pcurrent=l.pcurrent;//指針數據可以直接賦值
}
//main.cpp
#include "Linklist.h"
#include <iostream>
using namespace std;
int main()
{
   int tempi;
   char tempc;
   cout <<"請輸入一個整數和一個字符:" <<endl;
   cin >>tempi >>tempc;
   Linklist a(tempi,tempc);
   a.Locate(tempi);
   a.Insert(1,'C');
   a.Insert(2,'B');
   a.Insert(3,'F');
   cout <<"After Insert" <<endl;
   a.Show();
   a.Locate('B');
   a.Delete();
   cout <<"After Delete" <<endl;
   a.Show();
   Linklist b(a);//創建一個鏈表b,并且將鏈表a復制到鏈表b
   cout <<"This is Linklist b" <<endl;
   b.Show();//顯示b鏈表中的內容
   a.Destroy();
   cout <<"After Destroy" <<endl;
   a.Show();
   return 0;
}

運行結果:
請輸入一個整數和一個字符:
4 G
Node constructor is running...
Linklist constructor is running...
Node constructor is running...
Node constructor is running...
Node constructor is running...
After Insert
4 G
3 F
2 B
1 C
After Delete
4 G
3 F
1 C
Linklist cloner running...
This is Linklist b
4 G
3 F
1 C
After Destroy
4 G
根據程序運行的結果,我們發現輸出鏈表b的內容的確和鏈表a一樣了,并且我們可以得到三個結論:
(1) 拷貝構造函數可以讀出相同類對象的私有成員數據;
(2) 拷貝構造函數的實質是把參數的成員數據一一復制到新的對象中;
(3) 拷貝構造函數也是構造函數的一種重載。

默認拷貝構造函數

我們已經知道構造函數有默認構造函數,其實拷貝構造函數也有默認的拷貝構造函數。所謂默認拷貝構造函數是指,用戶沒有自己定義拷貝構造函數時,系統自動給出的一個拷貝構造函數。默認拷貝構造函數的功能是將對象的成員數據一一賦值給新創建的對象的成員數據,如果某些成員數據本身就是對象,則自動調用它們的拷貝構造函數或默認拷貝構造函數。

拷貝構造函數存在的意義

既然上面說到,默認拷貝構造函數已經能夠滿足我們大多數的需要,那么自定義的拷貝構造函數是否就可以不用存在了呢?我們修改一下程序15.4.1的main.cpp文件,看看拷貝構造函數到底有什么意義:
#include "Linklist.h"
#include <iostream>
using namespace std;
int main()
{
   int tempi;
   char tempc;
   cout <<"請輸入一個整數和一個字符:" <<endl;
   cin >>tempi >>tempc;
   Linklist a(tempi,tempc);
   a.Locate(tempi);
   a.Insert(1,'C');
   a.Insert(2,'B');
   a.Insert(3,'F');
   cout <<"After Insert" <<endl;
   a.Show();
   a.Locate('B');
   a.Delete();
   cout <<"After Delete" <<endl;
   a.Show();
   Linklist b(a);
   cout <<"This is Linklist B" <<endl;
   b.Show();
   a.Destroy();
   cout <<"After Destroy" <<endl;
   a.Show();
   cout <<"This is Linklist b" <<endl;
   b.Show();//關鍵是在這里加了一條語句,讓它顯示b鏈表中的內容
   return 0;
}
運行結果:
C++教程:C++拷貝構造函數
為什么顯示鏈表b的內容,卻導致了嚴重的錯誤呢?

這時我們就要來研究一下這個鏈表的結構了。在這個鏈表中,成員數據只有頭結點head和當前指針pcurrent,所有的結點都是通過new語句動態生成的。而程序15.4.1中的拷貝構造函數僅僅是簡單地將頭結點head和當前指針pcurrent復制了出來,所以一旦運行a.Destroy()之后,鏈表a頭結點之后的結點已經全部都刪除了,而鏈表b的頭結點還傻傻地指向原來a鏈表的結點。如果這時再訪問鏈表b,肯定就要出問題了。如下所示:
C++教程:C++拷貝構造函數
程序15.4.1中的拷貝構造函數僅僅是把成員數據拷貝了過來,卻沒有把動態申請的資源拷貝過來,我們把這種拷貝稱為淺拷貝。相對地,如果拷貝構造函數不僅把成員數據拷貝過來,連動態申請的資源也拷貝過來,我們則稱之為深拷貝。

下面我們來看如何實現深拷貝:(程序15.4.2)
//node.h同程序15.4.1
//linklist.h
#include "node.h"//需要使用鏈表結點類
#include <iostream>
using namespace std; 
class Linklist
{
   public:
   Linklist(int i,char c);//鏈表類構造函數
   Linklist(Linklist &l);//鏈表深拷貝構造函數
   bool Locate(int i);//根據整數查找結點
   bool Locate(char c);//根據字符查找結點
   bool Insert(int i=0,char c='0');//在當前結點之后插入結點
   bool Delete();//刪除當前結點
   void Show();//顯示鏈表所有數據
   void Destroy();//清除整個鏈表
   private:
   Node head;//頭結點
   Node * pcurrent;//當前結點指針
};
//未定義的函數與程序15.3相同
Linklist::Linklist(Linklist &l):head(l.head)
{
   cout<<"Linklist Deep cloner running..." <<endl;
   pcurrent=&head;
   Node * ptemp1=l.head.readn();//該指針用于指向原鏈表中被復制的結點
   while(ptemp1!=NULL)
   {
      Node * ptemp2=new Node(ptemp1->readi(),ptemp1->readc(),pcurrent,NULL);//新建結點,并復制idata和cdata,思考為何這里不能直接用Node的拷貝構造函數?
      pcurrent->setn(ptemp2);
      pcurrent=pcurrent->readn();//指向表尾結點
      ptemp1=ptemp1->readn();//指向下一個被復制結點
   }
}
//main.cpp
#include "Linklist.h"
#include <iostream>
using namespace std;
int main()
{
   int tempi;
   char tempc;
   cout <<"請輸入一個整數和一個字符:" <<endl;
   cin >>tempi >>tempc;
   Linklist a(tempi,tempc);
   a.Locate(tempi);
   a.Insert(1,'C');
   a.Insert(2,'B'); 
   a.Insert(3,'F');
   cout <<"After Insert" <<endl;
   a.Show();
   a.Locate('B');
   a.Delete();
   cout <<"After Delete" <<endl;
   a.Show();
   Linklist b(a);//創建一個鏈表b,并且將鏈表a復制到鏈表b
   cout <<"This is Linklist b" <<endl;
   b.Show();
   a.Destroy();
   cout <<"After Destroy" <<endl;
   a.Show();
   cout <<"This is Linklist b" <<endl;
   b.Show();//鏈表a被Destroy之后察看鏈表b的內容
   return 0;
}

運行結果:
請輸入一個整數和一個字符:
4 G
Node constructor is running...
Linklist constructor is running...
Node constructor is running...
Node constructor is running...
Node constructor is running...
After Insert
4 G
3 F
2 B
1 C
After Delete
4 G
3 F
1 C
Linklist Deep cloner running...
Node constructor is running...
Node constructor is running...
This is Linklist b
4 G
3 F
1 C
After Destroy
4 G
This is Linklist b
4 G
3 F
1 C
我們看到,現在即使運行a.Destroy()之后,鏈表b里面的數據仍然能夠正常顯示。這是因為深拷貝構造函數是真正意義上的復制了鏈表a,并且使得鏈表a和鏈表b各自獨立,互不干擾。這才是自定義拷貝構造函數存在的重要意義。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲奶大毛多的老太婆| 欧美丰满少妇xxxxx| 国产精品高精视频免费| 国产精品v日韩精品| 亚洲精品国产精品自产a区红杏吧| 亚洲精品综合久久中文字幕| 成人久久一区二区三区| 国产婷婷97碰碰久久人人蜜臀| 色综合视频一区中文字幕| 这里只有视频精品| 日韩网站免费观看| 国产成人啪精品视频免费网| 亚洲欧美日韩国产中文专区| 久久久久久这里只有精品| 国产精品美女在线| 中文字幕亚洲一区二区三区五十路| 亚洲影院在线看| 精品国产福利视频| 久久影视电视剧免费网站清宫辞电视| 亚洲va男人天堂| 岛国av一区二区| 国产精品美女999| 国产日本欧美一区| 日韩av在线电影网| 欧美超级乱淫片喷水| 久久久久久久久久久网站| 欧美一区二区三区艳史| 91视频免费网站| 在线日韩第一页| 日韩美女写真福利在线观看| 97**国产露脸精品国产| 伊人一区二区三区久久精品| 国产丝袜一区二区三区免费视频| 亚洲欧美国产精品| 日韩av电影中文字幕| 久久久久久久久91| 一区二区在线免费视频| 高清日韩电视剧大全免费播放在线观看| 91成人免费观看网站| 国产精品成久久久久三级| 国产精品一区二区久久国产| 4388成人网| 精品久久久国产精品999| 亚洲成在人线av| 久久久久久久久爱| 韩国19禁主播vip福利视频| 亚洲电影中文字幕| 国产91精品视频在线观看| 在线视频一区二区| 久久久久久久一区二区三区| 成人精品网站在线观看| 九九热最新视频//这里只有精品| 久久久久久久国产精品| 日本欧美中文字幕| 欧美激情中文字幕乱码免费| 日本中文字幕久久看| 欧美成人性色生活仑片| 性色av一区二区三区在线观看| 久久九九国产精品怡红院| 亚洲欧美制服综合另类| 精品国产网站地址| 欧美成人黄色小视频| 中文字幕日韩专区| 国产精品免费久久久久影院| 亚洲欧美一区二区三区情侣bbw| 国产精品扒开腿做爽爽爽视频| 久久久久久久久亚洲| 亚洲人成人99网站| 亚洲美女又黄又爽在线观看| 一本色道久久88综合亚洲精品ⅰ| 97久久伊人激情网| 91精品视频免费观看| 成人日韩av在线| 亚洲天堂av女优| 日韩亚洲国产中文字幕| 一区二区三区视频免费| 亚洲网站在线观看| xxxxxxxxx欧美| 美女性感视频久久久| 中文字幕在线成人| 久久噜噜噜精品国产亚洲综合| 91久久精品美女| 中文字幕日韩有码| 亚洲一区制服诱惑| 91社影院在线观看| 国产精品91久久| 91精品国产91久久| 国产丝袜一区二区| 久久国产精品网站| 久久久久国产视频| 最新亚洲国产精品| 性欧美长视频免费观看不卡| 精品无人区乱码1区2区3区在线| 亚洲精品电影网| 亚洲福利视频二区| 大伊人狠狠躁夜夜躁av一区| 欧美久久精品午夜青青大伊人| 国产精品一区二区av影院萌芽| 精品一区电影国产| 亚洲免费精彩视频| 欧美黑人又粗大| 欧美精品在线免费播放| 日本高清视频精品| 亚洲第一精品久久忘忧草社区| 欧美性视频网站| 91亚洲精品一区二区| 91精品国产高清久久久久久| 国产欧美亚洲视频| 欧美在线观看一区二区三区| 成人动漫网站在线观看| 日韩欧美国产激情| 国产精品老牛影院在线观看| 日本精品性网站在线观看| 国产精品1区2区在线观看| 九九久久精品一区| 国产精品高潮呻吟久久av野狼| 亚洲色图欧美制服丝袜另类第一页| 欧美插天视频在线播放| 日韩欧美a级成人黄色| 国产亚洲精品久久久久久牛牛| 亚洲精品一区二区网址| 538国产精品一区二区在线| 亚洲欧洲日产国码av系列天堂| 精品国产31久久久久久| 亚洲国产高潮在线观看| 青青草99啪国产免费| 亚洲少妇中文在线| 亚洲理论在线a中文字幕| 国产69精品久久久久久| 国产午夜精品全部视频播放| 欧美日韩国产综合视频在线观看中文| 亚洲国产私拍精品国模在线观看| 欧美激情网友自拍| 另类天堂视频在线观看| 欧美老少做受xxxx高潮| 中文字幕亚洲图片| 国产视频精品久久久| 国产亚洲视频中文字幕视频| 91久久精品国产91久久性色| 国产精品678| 欧美激情视频在线观看| 亚洲人成电影网站色xx| 亚洲第一在线视频| 欧美另类交人妖| 91免费欧美精品| 亚洲欧美在线免费观看| 欧美日韩免费观看中文| 亚州av一区二区| 亚洲自拍小视频| 欧美美最猛性xxxxxx| 欧美激情中文网| 欧美夫妻性生活视频| 亚洲综合国产精品| 91成人精品网站| 国产精品久久色| 久久久久久噜噜噜久久久精品| 国产精品永久免费| 国产一区视频在线| 久久久之久亚州精品露出| 欧美亚洲成人xxx| 久久久久五月天| 亚洲伊人一本大道中文字幕| 国产香蕉一区二区三区在线视频| 国产精品第3页|