欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++中復(fù)制構(gòu)造函數(shù)和重載賦值操作符總結(jié)

 更新時(shí)間:2014年10月09日 09:28:03   作者:果凍想  
這篇文章主要介紹了C++中復(fù)制構(gòu)造函數(shù)和重載賦值操作符總結(jié),本文對(duì)復(fù)制構(gòu)造函數(shù)和重載賦值操作符的定義、調(diào)用時(shí)機(jī)、實(shí)現(xiàn)要點(diǎn)、細(xì)節(jié)等做了總結(jié),需要的朋友可以參考下

前言

這篇文章將對(duì)C++中復(fù)制構(gòu)造函數(shù)和重載賦值操作符進(jìn)行總結(jié),包括以下內(nèi)容:

1.復(fù)制構(gòu)造函數(shù)和重載賦值操作符的定義;
2.復(fù)制構(gòu)造函數(shù)和重載賦值操作符的調(diào)用時(shí)機(jī);
3.復(fù)制構(gòu)造函數(shù)和重載賦值操作符的實(shí)現(xiàn)要點(diǎn);
4.復(fù)制構(gòu)造函數(shù)的一些細(xì)節(jié)。

復(fù)制構(gòu)造函數(shù)和重載賦值操作符的定義

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

復(fù)制代碼 代碼如下:

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

對(duì)于構(gòu)造函數(shù)和析構(gòu)函數(shù)不是今天總結(jié)的重點(diǎn),今天的重點(diǎn)是復(fù)制構(gòu)造函數(shù)和重載賦值操作。類的復(fù)制構(gòu)造函數(shù)原型如下:
復(fù)制代碼 代碼如下:

class_name(const class_name &src);

一般來(lái)說(shuō),如果我們沒有編寫復(fù)制構(gòu)造函數(shù),那么編譯器會(huì)自動(dòng)地替每一個(gè)類創(chuàng)建一個(gè)復(fù)制構(gòu)造函數(shù)(也叫隱式復(fù)制構(gòu)造函數(shù));相反的,如果我們編寫了一個(gè)復(fù)制構(gòu)造函數(shù)(顯式的復(fù)制構(gòu)造函數(shù)),那么編譯器就不會(huì)創(chuàng)建它。

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

復(fù)制代碼 代碼如下:

void operator=(const class_name &);

重載賦值操作符是一個(gè)特別的賦值運(yùn)算符,通常是用來(lái)把已存在的對(duì)象指定給其它相同類型的對(duì)象。它是一個(gè)特別的成員函數(shù),如果我們沒有定義這個(gè)成員函數(shù),那么編譯器會(huì)自動(dòng)地產(chǎn)生這個(gè)成員函數(shù)。編譯器產(chǎn)生的代碼是以單一成員進(jìn)行對(duì)象復(fù)制的動(dòng)作。

總結(jié)了復(fù)制構(gòu)造函數(shù)和重載賦值操作符的定義,只是讓我們了解了它們,而沒有真正的深入它們。接下來(lái),再仔細(xì)的總結(jié)一下它們的調(diào)用時(shí)機(jī)。關(guān)于它們的調(diào)用時(shí)機(jī),我一直都沒有真正的明白過(guò),所以這里一定要好好的總結(jié)明白了。

復(fù)制構(gòu)造函數(shù)和重載賦值操作符的調(diào)用時(shí)機(jī)

對(duì)復(fù)制構(gòu)造函數(shù)和重載賦值操作符的調(diào)用總是發(fā)生在不經(jīng)意間,它們不是經(jīng)過(guò)我們顯式的去調(diào)用就被執(zhí)行了。對(duì)于這種隱式調(diào)用的地方一定要多注意了,這也一般是有陷阱的地方?,F(xiàn)在我就用實(shí)際的例子來(lái)進(jìn)行驗(yàn)證;例子如下:

復(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); // 調(diào)用復(fù)制構(gòu)造函數(shù)
 
     obj1 = obj; // 調(diào)用重載賦值操作符
 
     /* 傳參的過(guò)程中,要調(diào)用一次復(fù)制構(gòu)造函數(shù)
     * obj1入棧時(shí)會(huì)調(diào)用復(fù)制構(gòu)造函數(shù)創(chuàng)建一個(gè)臨時(shí)對(duì)象,與函數(shù)內(nèi)的局部變量具有相同的作用域
     */
     obj.Test(obj1);
 
     /* 函數(shù)返回值時(shí),調(diào)用復(fù)制構(gòu)造函數(shù);將返回值賦值給obj2時(shí),調(diào)用重載賦值操作符
     * 函數(shù)返回值時(shí),也會(huì)構(gòu)造一個(gè)臨時(shí)對(duì)象;調(diào)用復(fù)制構(gòu)造函數(shù)將返回值復(fù)制到臨時(shí)對(duì)象上
     */
     CTest obj2;
     obj2 = obj.Test2();
 
     obj2.Test3(obj); // 參數(shù)是引用,沒有調(diào)用復(fù)制構(gòu)造函數(shù)
 
     CTest obj3;
     obj2.Test4(); // 返回值是引用,沒有調(diào)用復(fù)制構(gòu)造函數(shù)
 
     return 0;
}

在代碼中都加入了注釋,這里就不再做詳細(xì)的說(shuō)明了。再次總結(jié)一下,如果對(duì)象在聲明的同時(shí)將另一個(gè)已存在的對(duì)象賦給它,就會(huì)調(diào)用復(fù)制構(gòu)造函數(shù);如果對(duì)象已經(jīng)存在了,然后再將另一個(gè)已存在的對(duì)象賦給它,調(diào)用的就是重載賦值運(yùn)算符了。這條規(guī)則很適用,希望大家能記住。

復(fù)制構(gòu)造函數(shù)和重載賦值操作符的實(shí)現(xiàn)要點(diǎn)

在一般的情況下,編譯器給我們生成的默認(rèn)的復(fù)制構(gòu)造函數(shù)和重載賦值操作符就已經(jīng)夠用了;但是在一些特別的時(shí)候,需要我們手動(dòng)去實(shí)現(xiàn)自己的復(fù)制構(gòu)造函數(shù)。

我們都知道,默認(rèn)的復(fù)制構(gòu)造函數(shù)和賦值運(yùn)算符進(jìn)行的都是”shallow copy”,只是簡(jiǎn)單地復(fù)制字段,因此如果對(duì)象中含有動(dòng)態(tài)分配的內(nèi)存,就需要我們自己重寫復(fù)制構(gòu)造函數(shù)或者重載賦值運(yùn)算符來(lái)實(shí)現(xiàn)”deep copy”,確保數(shù)據(jù)的完整性和安全性。這也就是大家常常說(shuō)的深拷貝與淺拷貝的問(wèn)題。下面我就提供一個(gè)比較簡(jiǎn)單的例子來(lái)說(shuō)明一下:

復(fù)制代碼 代碼如下:

#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; // 方恒剛指出的問(wèn)題。非常感謝 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;
}

特別是在實(shí)現(xiàn)重載賦值構(gòu)造函數(shù)時(shí)需要多多的注意,在代碼中我也添加了注釋,大家可以認(rèn)真的閱讀一下代碼,然后就懂了,如果不懂的就可以留言問(wèn)我;當(dāng)然了,如果我哪里理解錯(cuò)了,也希望大家能給我提出,我們共同進(jìn)步。

復(fù)制構(gòu)造函數(shù)的一些細(xì)節(jié)

1.以下哪些是復(fù)制構(gòu)造函數(shù)

復(fù)制代碼 代碼如下:

X::X(const X&);  
X::X(X);  
X::X(X&, int a=1);  
X::X(X&, int a=1, int b=2);

這些細(xì)節(jié)問(wèn)題在這里也說(shuō)一說(shuō),我也是從別人的博客里看到的,這里自己也總結(jié)一下。對(duì)于一個(gè)類X, 如果一個(gè)構(gòu)造函數(shù)的第一個(gè)參數(shù)是下列之一:
復(fù)制代碼 代碼如下:

a) X&
b) const X&
c) volatile X&
d) const volatile X&

且沒有其他參數(shù)或其他參數(shù)都有默認(rèn)值,那么這個(gè)函數(shù)是拷貝構(gòu)造函數(shù)。
復(fù)制代碼 代碼如下:

X::X(const X&);  //是拷貝構(gòu)造函數(shù)  
X::X(X&, int=1); //是拷貝構(gòu)造函數(shù) 
X::X(X&, int a=1, int b=2); //當(dāng)然也是拷貝構(gòu)造函數(shù)

2.類中可以存在超過(guò)一個(gè)拷貝構(gòu)造函數(shù)

復(fù)制代碼 代碼如下:

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

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

總結(jié)

這篇文章對(duì)復(fù)制構(gòu)造函數(shù)和重載賦值操作符進(jìn)行了一些總結(jié),重點(diǎn)是在復(fù)制構(gòu)造函數(shù)與重載賦值操作符的調(diào)用時(shí)機(jī)上;對(duì)于大家喜歡總結(jié)的深拷貝與淺拷貝問(wèn)題,我沒有用過(guò)多的文字進(jìn)行說(shuō)明,我認(rèn)為上面的代碼就足以說(shuō)明問(wèn)題了。最后自己糾結(jié)已久的問(wèn)題也就這樣總結(jié)了,自己也徹底的明白了。

相關(guān)文章

  • 冒泡算法的改進(jìn)具體實(shí)現(xiàn)

    冒泡算法的改進(jìn)具體實(shí)現(xiàn)

    這篇文章主要介紹了冒泡算法的改進(jìn)具體實(shí)現(xiàn),有需要的朋友可以參考一下
    2013-12-12
  • OpenCV實(shí)現(xiàn)輪廓的發(fā)現(xiàn)

    OpenCV實(shí)現(xiàn)輪廓的發(fā)現(xiàn)

    這篇文章主要為大家詳細(xì)介紹了OpenCV如何實(shí)現(xiàn)輪廓的發(fā)現(xiàn),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-05-05
  • C\C++實(shí)現(xiàn)讀寫二進(jìn)制文件的方法詳解

    C\C++實(shí)現(xiàn)讀寫二進(jìn)制文件的方法詳解

    這篇文章主要為大家詳細(xì)介紹了C\C++實(shí)現(xiàn)讀寫二進(jìn)制文件的方法,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,感興趣的小伙伴可以了解一下
    2023-03-03
  • 詳解C++之類和對(duì)象(1)

    詳解C++之類和對(duì)象(1)

    類是創(chuàng)建對(duì)象的模板,一個(gè)類可以創(chuàng)建多個(gè)對(duì)象,每個(gè)對(duì)象都是類類型的一個(gè)變量;創(chuàng)建對(duì)象的過(guò)程也叫類的實(shí)例化。每個(gè)對(duì)象都是類的一個(gè)具體實(shí)例(Instance),擁有類的成員變量和成員函數(shù)
    2021-11-11
  • 使用C++實(shí)現(xiàn)Excel文件與CSV之間的相互轉(zhuǎn)換

    使用C++實(shí)現(xiàn)Excel文件與CSV之間的相互轉(zhuǎn)換

    這篇文章主要為大家詳細(xì)介紹了如何使用C++實(shí)現(xiàn)Excel文件與CSV之間的相互轉(zhuǎn)換,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下
    2023-06-06
  • C語(yǔ)言匯編分析傳遞結(jié)構(gòu)體指針比傳遞結(jié)構(gòu)體變量高效的深層原因

    C語(yǔ)言匯編分析傳遞結(jié)構(gòu)體指針比傳遞結(jié)構(gòu)體變量高效的深層原因

    本文章使用的工具是vs2010,本篇文章主要講解結(jié)構(gòu)體指針作為參數(shù)傳遞與結(jié)構(gòu)體變量作為參數(shù)傳遞的對(duì)比,不談值傳遞與址傳遞的概念
    2022-10-10
  • C++二叉樹結(jié)構(gòu)的建立與基本操作

    C++二叉樹結(jié)構(gòu)的建立與基本操作

    二叉樹是數(shù)據(jù)結(jié)構(gòu)中的樹的一種特殊情況,有關(guān)二叉樹的相關(guān)概念,這里不再贅述,如果不了解二叉樹相關(guān)概念,建議先學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)中的二叉樹的知識(shí)點(diǎn)
    2013-10-10
  • C?語(yǔ)言注釋和變量使用基礎(chǔ)詳解

    C?語(yǔ)言注釋和變量使用基礎(chǔ)詳解

    這篇文章主要為大家介紹了C語(yǔ)言注釋和變量使用示例基礎(chǔ)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-12-12
  • 記逆向小白的第一次vbsedit 9爆破及內(nèi)存補(bǔ)丁制作過(guò)程

    記逆向小白的第一次vbsedit 9爆破及內(nèi)存補(bǔ)丁制作過(guò)程

    這篇文章主要介紹了記逆向小白的第一次vbsedit 9爆破及內(nèi)存補(bǔ)丁制作過(guò)程,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-04-04
  • C++常用函數(shù)之XML JSON格式轉(zhuǎn)換問(wèn)題

    C++常用函數(shù)之XML JSON格式轉(zhuǎn)換問(wèn)題

    XML在Json出現(xiàn)前應(yīng)用很廣泛,靈活性好,應(yīng)用語(yǔ)言也沒有限制,發(fā)展了這么長(zhǎng)時(shí)間后xml標(biāo)準(zhǔn)已經(jīng)很臃腫。這篇文章主要介紹了C++常用函數(shù)之XML JSON格式轉(zhuǎn)換問(wèn)題,需要的朋友可以參考下
    2020-02-02

最新評(píng)論