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

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

C++中復制構造函數和重載賦值操作符總結

2020-01-26 15:15:48
字體:
來源:轉載
供稿:網友

前言

這篇文章將對C++中復制構造函數和重載賦值操作符進行總結,包括以下內容:

1.復制構造函數和重載賦值操作符的定義;
2.復制構造函數和重載賦值操作符的調用時機;
3.復制構造函數和重載賦值操作符的實現要點;
4.復制構造函數的一些細節。

復制構造函數和重載賦值操作符的定義

我們都知道,在C++中建立一個類,這個類中肯定會包括構造函數、析構函數、復制構造函數和重載賦值操作;即使在你沒有明確定義的情況下,編譯器也會給你生成這樣的四個函數。例如以下類:

復制代碼 代碼如下:

class CTest
{
public:
     CTest();
     ~CTest();
 
     CTest(const CTest &);
     void operator=(const CTest &);
};

對于構造函數和析構函數不是今天總結的重點,今天的重點是復制構造函數和重載賦值操作。類的復制構造函數原型如下:
復制代碼 代碼如下:

class_name(const class_name &src);

一般來說,如果我們沒有編寫復制構造函數,那么編譯器會自動地替每一個類創建一個復制構造函數(也叫隱式復制構造函數);相反的,如果我們編寫了一個復制構造函數(顯式的復制構造函數),那么編譯器就不會創建它。

類的重載賦值操作符的原型如下:

復制代碼 代碼如下:

void operator=(const class_name &);

重載賦值操作符是一個特別的賦值運算符,通常是用來把已存在的對象指定給其它相同類型的對象。它是一個特別的成員函數,如果我們沒有定義這個成員函數,那么編譯器會自動地產生這個成員函數。編譯器產生的代碼是以單一成員進行對象復制的動作。

總結了復制構造函數和重載賦值操作符的定義,只是讓我們了解了它們,而沒有真正的深入它們。接下來,再仔細的總結一下它們的調用時機。關于它們的調用時機,我一直都沒有真正的明白過,所以這里一定要好好的總結明白了。

復制構造函數和重載賦值操作符的調用時機

對復制構造函數和重載賦值操作符的調用總是發生在不經意間,它們不是經過我們顯式的去調用就被執行了。對于這種隱式調用的地方一定要多注意了,這也一般是有陷阱的地方?,F在我就用實際的例子來進行驗證;例子如下:

復制代碼 代碼如下:

#include <iostream>
using namespace std;
 
class CTest
{
public:
     CTest(){}
     ~CTest(){}
 
     CTest(const CTest &test)
     {
          cout<<"copy constructor."<<endl;
     }
 
     void operator=(const CTest &test)
     {
          cout<<"operator="<<endl;
     }
 
     void Test(CTest test)
     {}
 
     CTest Test2()
     {
          CTest a;
          return a;
     }
 
     void Test3(CTest &test)
     {}
 
     CTest &Test4()
     {
          CTest *pA = new CTest;
          return *pA;
     }
};
 
int main()
{
     CTest obj;
 
     CTest obj1(obj); // 調用復制構造函數
 
     obj1 = obj; // 調用重載賦值操作符
 
     /* 傳參的過程中,要調用一次復制構造函數
     * obj1入棧時會調用復制構造函數創建一個臨時對象,與函數內的局部變量具有相同的作用域
     */
     obj.Test(obj1);
 
     /* 函數返回值時,調用復制構造函數;將返回值賦值給obj2時,調用重載賦值操作符
     * 函數返回值時,也會構造一個臨時對象;調用復制構造函數將返回值復制到臨時對象上
     */
     CTest obj2;
     obj2 = obj.Test2();
 
     obj2.Test3(obj); // 參數是引用,沒有調用復制構造函數
 
     CTest obj3;
     obj2.Test4(); // 返回值是引用,沒有調用復制構造函數
 
     return 0;
}

在代碼中都加入了注釋,這里就不再做詳細的說明了。再次總結一下,如果對象在聲明的同時將另一個已存在的對象賦給它,就會調用復制構造函數;如果對象已經存在了,然后再將另一個已存在的對象賦給它,調用的就是重載賦值運算符了。這條規則很適用,希望大家能記住。

復制構造函數和重載賦值操作符的實現要點

在一般的情況下,編譯器給我們生成的默認的復制構造函數和重載賦值操作符就已經夠用了;但是在一些特別的時候,需要我們手動去實現自己的復制構造函數。

我們都知道,默認的復制構造函數和賦值運算符進行的都是”shallow copy”,只是簡單地復制字段,因此如果對象中含有動態分配的內存,就需要我們自己重寫復制構造函數或者重載賦值運算符來實現”deep copy”,確保數據的完整性和安全性。這也就是大家常常說的深拷貝與淺拷貝的問題。下面我就提供一個比較簡單的例子來說明一下:

復制代碼 代碼如下:

#include <iostream>
using namespace std;
 
const int MAXSIZE = 260;
 
class CTest
{
public:
     CTest(wchar_t *pInitValue)
     {
          // Here, I malloc the memory
          pValue = new wchar_t[MAXSIZE];
          memset(pValue, 0, sizeof(wchar_t) * MAXSIZE);
          wcscpy_s(pValue, MAXSIZE, pInitValue);
     }
 
     ~CTest()
     {
          if (pValue)
          {
               delete[] pValue; //finalseabiscuit指出,謝謝。2014.7.24
               pValue = NULL;
          }
     }
 
     CTest(const CTest &test)
     {
          // Malloc the new memory for the pValue
          pValue = new wchar_t[MAXSIZE];
          memset(pValue, 0, sizeof(wchar_t) * MAXSIZE);
          wcscpy_s(pValue, MAXSIZE, test.pValue);
     }
 
     CTest& operator=(const CTest &test)
     {
          // This is very important, please remember
          if (this == &test)
          {
               return *this;
          }
 
          // Please delete the memory, this maybe cause the memory leak
          if (pValue)
          {
               delete[] pValue; // 方恒剛指出的問題。非常感謝 2014.3.15
          }
 
          // Malloc the new memory for the pValue
          pValue = new wchar_t[MAXSIZE];
          memset(pValue, 0, sizeof(wchar_t) * MAXSIZE);
          wcscpy_s(pValue, MAXSIZE, test.pValue);
          return *this;
     }
 
     void Print()
     {
          wcout<<pValue<<endl;
     }
 
private:
     wchar_t *pValue; // The pointer points the memory
};
 
int main()
{
     CTest obj(L"obj");
     obj.Print();
 
     CTest obj2(L"obj2");
     obj2.Print();
     obj2 = obj;
     obj2.Print();
 
     obj2 = obj2;
     obj2.Print();
 
     return 0;
}

特別是在實現重載賦值構造函數時需要多多的注意,在代碼中我也添加了注釋,大家可以認真的閱讀一下代碼,然后就懂了,如果不懂的就可以留言問我;當然了,如果我哪里理解錯了,也希望大家能給我提出,我們共同進步。

復制構造函數的一些細節

1.以下哪些是復制構造函數

復制代碼 代碼如下:

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&

且沒有其他參數或其他參數都有默認值,那么這個函數是拷貝構造函數。
復制代碼 代碼如下:

X::X(const X&);  //是拷貝構造函數  
X::X(X&, int=1); //是拷貝構造函數 
X::X(X&, int a=1, int b=2); //當然也是拷貝構造函數

2.類中可以存在超過一個拷貝構造函數

復制代碼 代碼如下:

class X
{
public:      
  X(const X&);      // const 的拷貝構造
  X(X&);            // 非const的拷貝構造
};

注意,如果一個類中只存在一個參數為 X& 的拷貝構造函數,那么就不能使用const X或volatile X的對象實行拷貝初始化。如果一個類中沒有定義拷貝構造函數,那么編譯器會自動產生一個默認的拷貝構造函數。這個默認的參數可能為 X::X(const X&)或 X::X(X&),由編譯器根據上下文決定選擇哪一個。在我的Visual Studio 2012中,當定義了多個復制構造函數以后,編譯器就會有warning,但是程序還能正確運行。

總結

這篇文章對復制構造函數和重載賦值操作符進行了一些總結,重點是在復制構造函數與重載賦值操作符的調用時機上;對于大家喜歡總結的深拷貝與淺拷貝問題,我沒有用過多的文字進行說明,我認為上面的代碼就足以說明問題了。最后自己糾結已久的問題也就這樣總結了,自己也徹底的明白了。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
日韩小视频网址| 日韩在线不卡视频| 韩国国内大量揄拍精品视频| 136fldh精品导航福利| 亚洲免费成人av电影| 最近2019中文字幕mv免费看| 2021国产精品视频| 最近2019中文字幕第三页视频| 欧美不卡视频一区发布| 国产91色在线|| 庆余年2免费日韩剧观看大牛| 成人免费网站在线观看| 91色琪琪电影亚洲精品久久| 6080yy精品一区二区三区| 国产精品久久久久77777| 亚洲天堂男人的天堂| 91av视频在线观看| 国内精品久久影院| www.日韩欧美| 国产精品久久婷婷六月丁香| 成人a级免费视频| 亚洲加勒比久久88色综合| 97香蕉久久夜色精品国产| 久久精品美女视频网站| 欧美成人黄色小视频| 亚洲精品中文字幕女同| 日本三级韩国三级久久| 深夜福利亚洲导航| 秋霞午夜一区二区| 91豆花精品一区| 成人a级免费视频| 国内精品久久久久影院优| 成人激情电影一区二区| 亚洲激情免费观看| 日本高清视频一区| 亚洲最大福利网| 国产精品久久久久久av福利软件| 亚洲成色777777女色窝| 日韩av影院在线观看| 久久久中精品2020中文| 91丨九色丨国产在线| 97香蕉久久超级碰碰高清版| 一本色道久久综合狠狠躁篇怎么玩| 中文字幕精品一区久久久久| 欧美电影在线观看完整版| 深夜精品寂寞黄网站在线观看| 国产精品激情av在线播放| 久久久久久久成人| 最新的欧美黄色| 欧美日韩福利在线观看| 欧美精品videofree1080p| 九九久久久久久久久激情| 欧美极度另类性三渗透| 成人激情综合网| 国产一区二区视频在线观看| 国外成人在线直播| 日韩美女在线观看一区| 91嫩草在线视频| 欧美一级免费看| 51视频国产精品一区二区| 黑人与娇小精品av专区| 亚洲精品自产拍| 性日韩欧美在线视频| 国产精品美女在线观看| 国产一区二区欧美日韩| 久久久久久97| 欧美激情精品久久久久久免费印度| 国产精品午夜一区二区欲梦| 91久久久久久久久久| 狠狠干狠狠久久| 亚洲网在线观看| 不卡在线观看电视剧完整版| 亚洲嫩模很污视频| 91香蕉嫩草神马影院在线观看| 亚洲人成电影网站色xx| 欧美激情videoshd| 国产99久久久欧美黑人| 青草热久免费精品视频| 色悠久久久久综合先锋影音下载| 欧美丰满少妇xxxx| 欧美高清自拍一区| 国产日韩精品综合网站| 欧美另类99xxxxx| 亚洲免费av网址| 丝袜亚洲另类欧美重口| 午夜精品99久久免费| 国产热re99久久6国产精品| 欧美大奶子在线| 国产精品亚洲一区二区三区| 国产欧美日韩免费| 欧美俄罗斯乱妇| 成人深夜直播免费观看| 亚洲自拍另类欧美丝袜| 亚洲最大中文字幕| 欧美国产日韩中文字幕在线| 国产精品99免视看9| 在线视频一区二区| 亚洲天堂免费视频| 国产精品夜色7777狼人| 欧美性xxxxx极品| 欧美激情精品久久久久久变态| 九九视频这里只有精品| 日本免费在线精品| 亚洲综合精品一区二区| 久久久精品一区二区| 在线视频精品一| 欧美日韩黄色大片| 97热精品视频官网| 成人网在线视频| 综合136福利视频在线| 欧美性视频在线| 中文字幕精品影院| 91免费精品国偷自产在线| 久久久www成人免费精品| 国内精品久久久| 日韩精品中文字幕有码专区| 国产精品久久久久av免费| 欧美激情videoshd| 日本成熟性欧美| 久久深夜福利免费观看| 亚洲一二在线观看| 播播国产欧美激情| 国产成人激情小视频| 国产精品丝袜视频| 91经典在线视频| 日本精品久久久久影院| 亚洲女在线观看| 国产亚洲精品综合一区91| 欧美日韩性视频| 国产成人综合精品| 欧美黄色性视频| 91精品久久久久久久久不口人| 欧美性xxxxx极品| 91产国在线观看动作片喷水| 久久精品国产亚洲精品2020| 亚洲午夜未满十八勿入免费观看全集| 亚洲国产精品视频在线观看| 久久视频免费在线播放| 欧美激情视频一区二区三区不卡| 在线日韩日本国产亚洲| 欧美日韩另类视频| 欧美国产精品日韩| 日产精品久久久一区二区福利| 精品视频在线播放色网色视频| 亚洲另类xxxx| 国模极品一区二区三区| 国产精品久久久久aaaa九色| 日本精品久久中文字幕佐佐木| 黑人巨大精品欧美一区二区免费| 日本视频久久久| 亚洲国产欧美自拍| 亚洲精品黄网在线观看| 成人精品一区二区三区电影黑人| 欧美三级欧美成人高清www| 久久综合亚洲社区| 亚洲第一区第二区| 97色在线观看免费视频| 91爱视频在线| 中国日韩欧美久久久久久久久| 久久69精品久久久久久国产越南| 欧美怡春院一区二区三区| 久久久久久综合网天天| 爽爽爽爽爽爽爽成人免费观看| 国产精品黄色影片导航在线观看|