日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C++之拷贝函数

發(fā)布時間:2023/12/19 c/c++ 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++之拷贝函数 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

拷貝構(gòu)造函數(shù)是一種特殊的構(gòu)造函數(shù),函數(shù)的名稱必須和類名稱一致,它的唯一的一個參數(shù)是本類型的一個引用變量,該參數(shù)是const類型,不可變的。例如:類X的拷貝構(gòu)造函數(shù)的形式為X(X& x)。

以下情況都會調(diào)用拷貝構(gòu)造函數(shù):
一個對象以值傳遞的方式傳入函數(shù)體
一個對象以值傳遞的方式從函數(shù)返回
一個對象需要通過另外一個對象進行初始化。

如果在類中沒有顯式地聲明一個拷貝構(gòu)造函數(shù),那么,編譯器將會自動生成一個默認的拷貝構(gòu)造函數(shù),該構(gòu)造函數(shù)完成對象之間的位拷貝。位拷貝又稱淺拷貝,后面將進行說明。

自定義拷貝構(gòu)造函數(shù)是一種良好的編程風格,它可以阻止編譯器形成默認的拷貝構(gòu)造函數(shù),提高源碼效率。

淺拷貝和深拷貝

  在某些狀況下,類內(nèi)成員變量需要動態(tài)開辟堆內(nèi)存,如果實行位拷貝,也就是把對象里的值完全復制給另一個對象,如A=B。這時,如果B中有一個成員變量指針已經(jīng)申請了內(nèi)存,那A中的那個成員變量也指向同一塊內(nèi)存。這就出現(xiàn)了問題:當B把內(nèi)存釋放了(如:析構(gòu)),這時A內(nèi)的指針就是野指針了,出現(xiàn)運行錯誤。

  深拷貝和淺拷貝可以簡單理解為:如果一個類擁有資源,當這個類的對象發(fā)生復制過程的時候,資源重新分配,這個過程就是深拷貝,反之,沒有重新分配資源,就是淺拷貝。
  
深拷貝和淺拷貝的定義可以簡單理解成:如果一個類擁有資源(堆,或者是其它系統(tǒng)資源),當這個類的對象發(fā)生復制過程的時候,這個過程就可以叫做深拷貝,反之對象存在資源,但復制過程并未復制資源的情況視為淺拷貝。

淺拷貝資源后在釋放資源的時候會產(chǎn)生資源歸屬不清的情況導致程序運行出錯。

代碼實現(xiàn):
拷貝構(gòu)造:

#include <stdio.h>class Test6_1 { public:Test6_1 (int a){m_a = a;printf ("普通構(gòu)造函數(shù)\n");}// 拷貝構(gòu)造Test6_1(const Test6_1 &obj){// m_a = obj.m_a;m_a = -100;printf ("拷貝構(gòu)造被調(diào)用\n");}~Test6_1(){printf ("***********析構(gòu)函數(shù)被調(diào)用: m_a = %d\n", m_a);}void print(){printf ("a = %d\n", m_a);} private:int m_a; };// void test(Test6_1 &t) void test(Test6_1 t) {t.print(); }Test6_1 test6_1() {Test6_1 t(10);return t; }// 函數(shù)返回值是一個對象 int main6_2() {// 一個函數(shù)返回一個對象的時候會創(chuàng)建一個匿名對象,拿返回的那個對象// 對匿名對象進行初始化,會調(diào)用拷貝構(gòu)造// 如果沒有去接收函數(shù)的返回值的話,匿名對象會立馬被銷毀// test6_1();// 如果用一個對象去接收函數(shù)的返回值,先用函數(shù)返回的對象去初始化// 匿名對象,調(diào)用一次拷貝構(gòu)造,然后拿新的對象的名字去命名這個匿名對象// 匿名對象從無名轉(zhuǎn)成有名// Test6_1 t1 = test6_1();Test6_1 t2(10);// 用函數(shù)返回的對象對匿名對象進行初始化,調(diào)用拷貝構(gòu)造// 用匿名對象對 t2 進行賦值,調(diào)用 賦值運算符 = t2 = test6_1();// 初始化、構(gòu)造、賦值int a; // 定義變量int b = 20; // 初始化a = 10; // 賦值printf ("-------------------------\n");return 0; }int main6_1() {// 1、直接初始化Test6_1 t1(10); #if 0Test6_1 t2(t1); // 拿 t1 取初始化 t2// 2、等于號Test6_1 t3 = t1;t3.print(); #endif // 3、當對象作為函數(shù)參數(shù)傳遞的時候會調(diào)用拷貝構(gòu)造test(t1);return 0; }

默認構(gòu)造函數(shù):

#include <stdio.h>class Test7_1 { public:Test7_1(){}Test7_1(int a){m_a = a;}void print (){printf ("m_a = %d\n", m_a);} private:int m_a; };// 如果類中沒有定義任何構(gòu)造函數(shù),編譯器會自動生成一個無參構(gòu)造函數(shù),沒有做任何事情 // 如果寫了構(gòu)造函數(shù),編譯器將不再提供默認的無參構(gòu)造函數(shù) // 如果還想進行無參構(gòu)造,需要顯示定義無參構(gòu)造函數(shù)// 如果沒有定義拷貝構(gòu)造函數(shù),編譯器會自動生成一個拷貝構(gòu)造函數(shù), // 會做普通類型數(shù)據(jù)的復制// 還會生成一個默認的 析構(gòu)函數(shù) class Test7_2 { #if 0Test7_2() {}Test7_2(const Test7_2 &obj) {}~Test7_2(){}; #endif };int main7_1() {Test7_1 b;Test7_1 a(10);Test7_1 c = a;a.print();c.print();return 0; }

深拷貝和淺拷貝:

#include <stdio.h> #include <string.h> #include <stdlib.h>// 淺拷貝:在拷貝指針的時候只是拷貝了地址,不會進行空間的復制 class Test8_1 { public:Test8_1(int id, char *name){m_id = id;m_name = (char *)malloc(sizeof(char)*20);strcpy (m_name, name);}~Test8_1(){if (m_name != NULL){free (m_name);m_name = NULL;}printf ("析構(gòu)被調(diào)用**********\n");}void print(){printf ("id = %d, name = %s\n", m_id, m_name);} private:int m_id; // char m_name[20];char *m_name; };// 深拷貝 class Test8_2 { public:Test8_2(int id, char *name){m_id = id;m_name = (char *)malloc(sizeof(char)*20);strcpy (m_name, name);}// 自己寫拷貝構(gòu)造函數(shù),避免淺拷貝Test8_2(const Test8_2 &obj){m_id = obj.m_id;m_name = (char *)malloc(sizeof(char)*20);strcpy (m_name, obj.m_name);}~Test8_2(){if (m_name != NULL){free (m_name);m_name = NULL;}printf ("析構(gòu)被調(diào)用**********\n");}void print(){printf ("id = %d, name = %s\n", m_id, m_name);} private:int m_id;char *m_name; };class Test8_3 { private:// 將拷貝構(gòu)造寫成私有的函數(shù),只需聲明,不需要實現(xiàn)Test8_3(const Test8_3 &ibj);public:Test8_3(int a){m_a = a;}private:int m_a; }; int main8_3() {Test8_3 t(10);// Test8_3 t1 = t;return 0; }int main8_2() {Test8_2 t1(10, "wang");t1.print();// 調(diào)用自己寫的拷貝構(gòu)造函數(shù),進行深拷貝Test8_2 t2 = t1;t2.print();return 0; }int main8_1() {Test8_1 t1(10, "wang");t1.print();// 調(diào)用默認的拷貝構(gòu)造函數(shù)Test8_1 t2 = t1;//t2.print();return 0; }

總結(jié)

以上是生活随笔為你收集整理的C++之拷贝函数的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。