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

詳解C++ 拷貝構造函數(shù)和賦值運算符

 更新時間:2016年12月08日 14:12:55   作者:Brook_icv  
本文主要介紹了拷貝構造函數(shù)和賦值運算符的區(qū)別,以及在什么時候調用拷貝構造函數(shù)、什么情況下調用賦值運算符。最后,簡單的分析了下深拷貝和淺拷貝的問題。有需要的朋友可以看下

本文主要介紹了拷貝構造函數(shù)和賦值運算符的區(qū)別,以及在什么時候調用拷貝構造函數(shù)、什么情況下調用賦值運算符。最后,簡單的分析了下深拷貝和淺拷貝的問題。

拷貝構造函數(shù)和賦值運算符

在默認情況下(用戶沒有定義,但是也沒有顯式的刪除),編譯器會自動的隱式生成一個拷貝構造函數(shù)和賦值運算符。但用戶可以使用delete來指定不生成拷貝構造函數(shù)和賦值運算符,這樣的對象就不能通過值傳遞,也不能進行賦值運算。

class Person
{
public:
 Person(const Person& p) = delete;
 Person& operator=(const Person& p) = delete;
private:
 int age;
 string name;
};

上面的定義的類Person顯式的刪除了拷貝構造函數(shù)和賦值運算符,在需要調用拷貝構造函數(shù)或者賦值運算符的地方,會提示_無法調用該函數(shù),它是已刪除的函數(shù)_。

還有一點需要注意的是,拷貝構造函數(shù)必須以引用的方式傳遞參數(shù)。這是因為,在值傳遞的方式傳遞給一個函數(shù)的時候,會調用拷貝構造函數(shù)生成函數(shù)的實參。如果拷貝構造函數(shù)的參數(shù)仍然是以值的方式,就會無限循環(huán)的調用下去,直到函數(shù)的棧溢出。

何時調用

拷貝構造函數(shù)和賦值運算符的行為比較相似,都是將一個對象的值復制給另一個對象;但是其結果卻有些不同,拷貝構造函數(shù)使用傳入對象的值生成一個新的對象的實例,而賦值運算符是將對象的值復制給一個已經(jīng)存在的實例。這種區(qū)別從兩者的名字也可以很輕易的分辨出來,拷貝構造函數(shù)也是一種構造函數(shù),那么它的功能就是創(chuàng)建一個新的對象實例;賦值運算符是執(zhí)行某種運算,將一個對象的值復制給另一個對象(已經(jīng)存在的)。調用的是拷貝構造函數(shù)還是賦值運算符,主要是看是否有新的對象實例產(chǎn)生。如果產(chǎn)生了新的對象實例,那調用的就是拷貝構造函數(shù);如果沒有,那就是對已有的對象賦值,調用的是賦值運算符。

調用拷貝構造函數(shù)主要有以下場景:

  • 對象作為函數(shù)的參數(shù),以值傳遞的方式傳給函數(shù)。 
  • 對象作為函數(shù)的返回值,以值的方式從函數(shù)返回
  • 使用一個對象給另一個對象初始化

代碼如下:

class Person
{
public:
 Person(){}
 Person(const Person& p)
 {
 cout << "Copy Constructor" << endl;
 }
 Person& operator=(const Person& p)
 {
 cout << "Assign" << endl;
 return *this;
 }
private:
 int age;
 string name;
};
void f(Person p)
{
 return;
}
Person f1()
{
 Person p;
 return p;
}
int main()
{
 Person p;
 Person p1 = p; // 1
 Person p2;
 p2 = p; // 2
 f(p2); // 3
 p2 = f1(); // 4
 Person p3 = f1(); // 5
 getchar();
 return 0;
}

上面代碼中定義了一個類Person,顯式的定義了拷貝構造函數(shù)和賦值運算符。然后定義了兩個函數(shù):f,以值的方式參傳入Person對象;f1,以值的方式返回Person對象。在main中模擬了5中場景,測試調用的是拷貝構造函數(shù)還是賦值運算符。執(zhí)行結果如下:

分析如下:

  1. 這是雖然使用了"=",但是實際上使用對象p來創(chuàng)建一個新的對象p1。也就是產(chǎn)生了新的對象,所以調用的是拷貝構造函數(shù)。
  2. 首先聲明一個對象p2,然后使用賦值運算符"=",將p的值復制給p2,顯然是調用賦值運算符,為一個已經(jīng)存在的對象賦值 。
  3. 以值傳遞的方式將對象p2傳入函數(shù)f內,調用拷貝構造函數(shù)構建一個函數(shù)f可用的實參。
  4. 這條語句拷貝構造函數(shù)和賦值運算符都調用了。函數(shù)f1以值的方式返回一個Person對象,在返回時會調用拷貝構造函數(shù)創(chuàng)建一個臨時對象tmp作為返回值;返回后調用賦值運算符將臨時對象tmp賦值給p2.
  5. 按照4的解釋,應該是首先調用拷貝構造函數(shù)創(chuàng)建臨時對象;然后再調用拷貝構造函數(shù)使用剛才創(chuàng)建的臨時對象創(chuàng)建新的對象p3,也就是會調用兩次拷貝構造函數(shù)。不過,編譯器也沒有那么傻,應該是直接調用拷貝構造函數(shù)使用返回值創(chuàng)建了對象p3。

深拷貝、淺拷貝

說到拷貝構造函數(shù),就不得不提深拷貝和淺拷貝。通常,默認生成的拷貝構造函數(shù)和賦值運算符,只是簡單的進行值的復制。例如:上面的Person類,字段只有int和string兩種類型,這在拷貝或者賦值時進行值復制創(chuàng)建的出來的對象和源對象也是沒有任何關聯(lián),對源對象的任何操作都不會影響到拷貝出來的對象。反之,假如Person有一個對象為int *,這時在拷貝時還只是進行值復制,那么創(chuàng)建出來的Person對象的int *的值就和源對象的int *指向的是同一個位置。任何一個對象對該值的修改都會影響到另一個對象,這種情況就是淺拷貝。

深拷貝和淺拷貝主要是針對類中的指針和動態(tài)分配的空間來說的,因為對于指針只是簡單的值復制并不能分割開兩個對象的關聯(lián),任何一個對象對該指針的操作都會影響到另一個對象。這時候就需要提供自定義的深拷貝的拷貝構造函數(shù),消除這種影響。通常的原則是:

  • 含有指針類型的成員或者有動態(tài)分配內存的成員都應該提供自定義的拷貝構造函數(shù)
  • 在提供拷貝構造函數(shù)的同時,還應該考慮實現(xiàn)自定義的賦值運算符

對于拷貝構造函數(shù)的實現(xiàn)要確保以下幾點:

  • 對于值類型的成員進行值復制
  • 對于指針和動態(tài)分配的空間,在拷貝中應重新分配分配空間
  • 對于基類,要調用基類合適的拷貝方法,完成基類的拷貝

總結

  • 拷貝構造函數(shù)和賦值運算符的行為比較相似,卻產(chǎn)生不同的結果;拷貝構造函數(shù)使用已有的對象創(chuàng)建一個新的對象,賦值運算符是將一個對象的值復制給另一個已存在的對象。區(qū)分是調用拷貝構造函數(shù)還是賦值運算符,主要是否有新的對象產(chǎn)生。
  • 關于深拷貝和淺拷貝。當類有指針成員或有動態(tài)分配空間,都應實現(xiàn)自定義的拷貝構造函數(shù)。提供了拷貝構造函數(shù),最后也實現(xiàn)賦值運算符。

以上就是本文的全部內容,希望本文的內容對大家的學習或者工作能帶來一定的幫助,如果有疑問大家可以留言交流,同時也希望多多支持腳本之家!

相關文章

  • 雙向鏈表插入刪除基本應用介紹

    雙向鏈表插入刪除基本應用介紹

    本文將詳細介紹建立雙向鏈表,實現(xiàn)對雙向鏈表的插入,刪除操作,需要了解的朋友可以參考下
    2012-11-11
  • C++同步線程實現(xiàn)示例詳解

    C++同步線程實現(xiàn)示例詳解

    這篇文章主要介紹了C++同步線程實現(xiàn)示例,線程同步是指同一進程中的多個線程互相協(xié)調工做從而達到一致性。之因此須要線程同步,是由于多個線程同時對一個數(shù)據(jù)對象進行修改操做時,可能會對數(shù)據(jù)形成破壞
    2022-11-11
  • VS+QT編譯環(huán)境中字符亂碼問題解決方法

    VS+QT編譯環(huán)境中字符亂碼問題解決方法

    編碼就是把?個字符編碼成二進制碼存起來的方式,而解碼就是把這個二進制碼按照原本編碼的規(guī)則還原成原來的字符,這篇文章主要介紹了VS+QT編譯環(huán)境中字符亂碼問題詳解,需要的朋友可以參考下
    2024-01-01
  • VS2017中配置QT5.12.0的圖文教程

    VS2017中配置QT5.12.0的圖文教程

    本文主要介紹了VS2017中配置QT5.12.0的圖文教程,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-06-06
  • 深入理解二叉樹的非遞歸遍歷

    深入理解二叉樹的非遞歸遍歷

    本篇文章是對二叉樹的非遞歸遍歷進行了詳細的分析介紹,需要的朋友參考下
    2013-05-05
  • 簡單掌握C++編程中的while與do-while循環(huán)語句使用

    簡單掌握C++編程中的while與do-while循環(huán)語句使用

    這篇文章主要介紹了C++編程中的while與do-while循環(huán)語句使用,區(qū)別就是while是先判斷再執(zhí)行,而do-while是先執(zhí)行再判斷,需要的朋友可以參考下
    2016-01-01
  • 基于C語言實現(xiàn)學生成績管理系統(tǒng)

    基于C語言實現(xiàn)學生成績管理系統(tǒng)

    這篇文章主要介紹了基于C語言實現(xiàn)學生成績管理系統(tǒng),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-01-01
  • 基于Qt播放器的實現(xiàn)詳解(支持Rgb,YUV格式)

    基于Qt播放器的實現(xiàn)詳解(支持Rgb,YUV格式)

    這篇文章主要為大家詳細介紹了如何利用Qt實現(xiàn)簡易的播放器,可以支持支持Rgb,YUV格式。文中的示例代碼講解詳細,感興趣的小伙伴可以嘗試一下
    2022-12-12
  • 不要被C++(自動生成規(guī)則)所蒙騙

    不要被C++(自動生成規(guī)則)所蒙騙

    正如標題所說,我們不要被C++語法中所描述的那些條條框框所“蒙騙”了。的確,相信這些生成規(guī)則不會對我們的編程帶來多大的影響(不會產(chǎn)生錯誤),但是只有了解它們的背后操作,我們才知道編譯器究竟為我們做了什么,感興趣的朋友可以了解下,希望本文對你有所幫助
    2013-01-01
  • C語言time.h庫函數(shù)的具體用法

    C語言time.h庫函數(shù)的具體用法

    C語言的time.h頭文件提供了一系列的函數(shù)和工具,用于處理時間和日期相關的操作,本文主要介紹了C語言time.h庫函數(shù)的具體用法,感興趣的可以了解一下
    2023-12-12

最新評論