C++之拷貝函數

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

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

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

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

淺拷貝和深拷貝

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

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

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

代碼實現:
拷貝構造:

#include <stdio.h>class Test6_1
{
public:Test6_1 (int a){m_a = a;printf ("普通構造函數\n");}// 拷貝構造Test6_1(const Test6_1 &obj){// m_a = obj.m_a;m_a = -100;printf ("拷貝構造被調用\n");}~Test6_1(){printf ("***********析構函數被調用: 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;
}// 函數返回值是一個對象
int main6_2()
{// 一個函數返回一個對象的時候會創建一個匿名對象,拿返回的那個對象// 對匿名對象進行初始化,會調用拷貝構造// 如果沒有去接收函數的返回值的話,匿名對象會立馬被銷毀// test6_1();// 如果用一個對象去接收函數的返回值,先用函數返回的對象去初始化// 匿名對象,調用一次拷貝構造,然后拿新的對象的名字去命名這個匿名對象// 匿名對象從無名轉成有名// Test6_1 t1 = test6_1();Test6_1 t2(10);// 用函數返回的對象對匿名對象進行初始化,調用拷貝構造// 用匿名對象對  t2  進行賦值,調用 賦值運算符  = t2 = test6_1();// 初始化、構造、賦值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、當對象作為函數參數傳遞的時候會調用拷貝構造test(t1);return 0;
}

默認構造函數:

#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;
};// 如果類中沒有定義任何構造函數,編譯器會自動生成一個無參構造函數,沒有做任何事情
// 如果寫了構造函數,編譯器將不再提供默認的無參構造函數
// 如果還想進行無參構造,需要顯示定義無參構造函數// 如果沒有定義拷貝構造函數,編譯器會自動生成一個拷貝構造函數,
// 會做普通類型數據的復制// 還會生成一個默認的 析構函數 
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 ("析構被調用**********\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);}// 自己寫拷貝構造函數,避免淺拷貝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 ("析構被調用**********\n");}void print(){printf ("id = %d, name = %s\n", m_id, m_name);}
private:int m_id;char *m_name;
};class Test8_3
{
private:// 將拷貝構造寫成私有的函數,只需聲明,不需要實現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();// 調用自己寫的拷貝構造函數,進行深拷貝Test8_2 t2 = t1;t2.print();return 0;
}int main8_1()
{Test8_1 t1(10, "wang");t1.print();// 調用默認的拷貝構造函數Test8_1 t2 = t1;//t2.print();return 0;
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/448404.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/448404.shtml
英文地址,請注明出處:http://en.pswp.cn/news/448404.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

spring Boot 學習(七、Spring Boot與開發熱部署)

一、熱部署在開發中我們修改一個Java文件后想看到效果不得不重啟應用&#xff0c;這導致大量時間 花費&#xff0c;我們希望不重啟應用的情況下&#xff0c;程序可以自動部署&#xff08;熱部署&#xff09;。有以下四 種情況&#xff0c;如何能實現熱部署。?1、模板引擎 – 在…

解決: Cannot find module ‘webpack-cli/bin/config-yargs‘、Error: Cannot find module ‘webpack-cli‘

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 npm 、cnpm 、node、vue 全都裝上了&#xff0c;就是 webpack 裝不上&#xff01;&#xff01; 最后我把整個服務器還原為初始設置了&…

路由器和交換機的區別詳解

很多人對路由器和交換機混為一談&#xff0c;甚至搞不清楚路由器和交換機有什么區別&#xff0c;有的用戶還認為是一樣的功能&#xff0c;看名字就知道是兩種不同的產品&#xff0c;功能雖然有些類似&#xff0c;但絕對不會完全相同&#xff0c;否則就沒有必要用兩個全面不同的…

C++之構造函數和析構函數強化

構造與析構調用順序: #include <stdio.h>class Test9_1 { public:Test9_1 (int a){m_a a;printf ("9_1 1111111111111111111構造函數....a: %d\n", a);}// 析構的順序和構造的順序相反&#xff0c;先構造的后析構~Test9_1(){printf ("9_1 1111111111111…

Oracle的逆向工程generatorConfig

<?xml version"1.0" encoding"UTF-8"?> <!DOCTYPE generatorConfigurationPUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN""http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"> <ge…

最簡單、圖解:阿里云服務器上裝 Docker 、 CentOS上 docker安裝(3分鐘裝完)

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 // 為了裝 vue 的 webpack &#xff0c;我把整個服務器重置了。docker 也沒有了&#xff0c;只好重新裝 docker ... 1. 準備工作 yum …

C++之對象的動態建立和釋放

new和delete的用法&#xff1a; 1&#xff09;在軟件開發過程中&#xff0c;常常需要動態地分配和撤銷內存空間&#xff0c;例如對動態鏈表中結點的插入與刪除。在C語言中是利用庫函數malloc和free來分配和撤銷內存空間的。C提供了較簡便而功能較強的運算符new和delete來取代m…

7.11牛客題(指針)

今天在牛客做錯了一道題&#xff0c;在此寫下感觸題目如下&#xff1a;若有說明:int i, j2,*p&i;,則能完成 ij 賦值功能的語句是&#xff08;B&#xff09;。A i*p; B *p*&j; C i&j; D i**p; 分析&#xff1a;題目中&#xff0c;p指針指向i的地址&#xff0c;A選項…

gpu簡介

GPU英文全稱Graphic Processing Unit&#xff0c;中文翻譯為“圖形處理器”。GPU是相對于CPU的一個概念&#xff0c;由于在現代的計算機中&#xff08;特別是家用系統&#xff0c;游戲的發燒友&#xff09;圖形的處理變得越來越重要&#xff0c;需要一個專門的圖形的核心處理器…

WM有約(五):部署應用程序

WM有約&#xff08;五&#xff09;&#xff1a;部署應用程序 Written by Allen Lee 創建安裝包 創建一個新的項目&#xff0c;用來部署Windows Mobile應用程序的項目模板是Other Project Types\Setup and Deployment下的Smart Device CAB Project&#xff1a; 圖 1 輸入項…

“ 我亦想望,如池魚悠悠 ... “

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 // 鬧鐘響了&#xff0c;起床&#xff0c;洗漱完畢&#xff0c;背上電腦出門&#xff0c;到公司打卡 8&#xff1a;20 。 " 我亦想…

C++之靜態成員變量和靜態成員函數

靜態成員變量 關鍵字 static 可以用于說明一個類的成員&#xff0c; 靜態成員提供了一個同類對象的共享機制 把一個類的成員說明為 static 時&#xff0c;這個類無論有多少個對象被創建&#xff0c;這些對象共享這個 static 成員 靜態成員局部于類&#xff0c;它不是對象成…

熄火/死火

定義 當反應器正在以顯著的反應速率進行操作時&#xff0c;若降低進料入口的溫度&#xff0c;使它達到多重態區域的下限&#xff0c;反應速度會突然大幅度下降&#xff0c;反應基本上停止。這個現象稱為熄滅。相應的入口溫度稱為熄滅點。一般指的是汽車熄火。發生原因 有…

H3C 以太網集線器

轉載于:https://www.cnblogs.com/fanweisheng/p/11169349.html

解決: WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 1. 問題描述&#xff1a;阿里云服務器 磁盤初始化之后用 git-bash ssh rootxx.xx.xx.xx 方式登陸服務器&#xff0c;報錯如下。 WARNIN…

C++之面向對象模型

C對象模型可以概括為以下2部分&#xff1a; 1. 語言中直接支持面向對象程序設計的部分&#xff0c;主要涉及如構造函數、析構函數、虛函數、繼承&#xff08;單繼承、多繼承、虛繼承&#xff09;、多態等等。 2. 對于各種支持的底層實現機制。 在c語言中&#xff0c;“數據”…

netty接收大文件的方法

參考:http://blog.csdn.net/linuu/article/details/51371595 https://www.jianshu.com/p/a0a51fd79f62 netty默認是只能接收1024個字節&#xff0c;但是我們要傳輸大文件怎么辦&#xff1f; 上代碼&#xff1a; 改之后服務端&#xff1a; package server;import io.netty.boots…

制動失靈

定義 制動過程中&#xff0c;由于制動器某些零部件的損壞或發生故障&#xff0c;使運動部件(或運動機械)不能保持停止狀態或不能按要求停止運動的現象。制動失靈的原因 制動失靈的關鍵在于制動系統無法對汽車施加足夠的制動力&#xff0c;包括制動液管路液位不足或進入…

webpack 入門,說一下那些不入流的知識點、module.exports{ } 中配置說明

先說說Vue-Cli&#xff08;Vue項目腳手架&#xff09; 前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 關于它能干什么&#xff0c;就不再贅述了&#xff0c;我們主要談談生成的與webp…

myeclipse2013 jad反編譯插件安裝

https://blog.csdn.net/zhenshixian88/article/details/26454319 1. 下載插件工具 http://download.csdn.net/detail/zwj_lmss/6697259 2. 里面有兩個文件 1).JAD.EXE隨便找個地方丟進去(我是隨便放哪邊的,不過有的人有問題,最后放在了jdk的bin下面.可能他們沒有配置環境變量);…