effective c++條款11擴展——關于拷貝構造函數和賦值運算符

effective c++條款11擴展——關于拷貝構造函數和賦值運算符
作者:馮明德


重點:包含動態分配成員的類 應提供拷貝構造函數,并重載"="賦值操作符。

以下討論中將用到的例子:

class CExample
{
public:
CExample(){pBuffer=NULL; nSize=0;}
~CExample(){delete pBuffer;}
void Init(int n){ pBuffer=new char[n]; nSize=n;}
private:
char *pBuffer; //類的對象中包含指針,指向動態分配的內存資源
int nSize;
};

這個類的主要特點是包含指向其他資源的指針。

pBuffer指向堆中分配的一段內存空間。

一、拷貝構造函數

int main(int argc, char* argv[])
{
CExample theObjone;
theObjone.Init40);
//現在需要另一個對象,需要將他初始化稱對象一的狀態
CExample theObjtwo=theObjone;
...
}

語句"CExample theObjtwo=theObjone;"用theObjone初始化theObjtwo。

其完成方式是內存拷貝,復制所有成員的值。

完成后,theObjtwo.pBuffer==theObjone.pBuffer。

即它們將指向同樣的地方,指針雖然復制了,但所指向的空間并沒有復制,而是由兩個對象共用了。這樣不符合要求,對象之間不獨立了,并為空間的刪除帶來隱患。

所以需要采用必要的手段來避免此類情況。

回顧以下此語句的具體過程:首先建立對象theObjtwo,并調用其構造函數,然后成員被拷貝。

可以在構造函數中添加操作來解決指針成員的問題。

所以C++語法中除了提供缺省形式的構造函數外,還規范了另一種特殊的構造函數:拷貝構造函數,上面的語句中,如果類中定義了拷貝構造函數,這對象建立時,調用的將是拷貝構造函數,在拷貝構造函數中,可以根據傳入的變量,復制指針所指向的資源。

?

拷貝構造函數的格式為:構造函數名(對象的引用)

提供了拷貝構造函數后的CExample類定義為:

class CExample
{
public:
CExample(){pBuffer=NULL; nSize=0;}
~CExample(){delete pBuffer;}
CExample(const CExample&); //拷貝構造函數
void Init(int n){ pBuffer=new char[n]; nSize=n;}
private:
char *pBuffer; //類的對象中包含指針,指向動態分配的內存資源
int nSize;
};
CExample::CExample(const CExample& RightSides) //拷貝構造函數的定義
{
nSize=RightSides.nSize; //復制常規成員
pBuffer=new char[nSize]; //復制指針指向的內容
memcpy(pBuffer,RightSides.pBuffer,nSize*sizeof(char));
}

這樣,定義新對象,并用已有對象初始化新對象時,CExample(const CExample& RightSides)將被調用,而已有對象用別名RightSides傳給構造函數,以用來作復制。

原則上,應該為所有包含動態分配成員的類都提供拷貝構造函數。

拷貝構造函數的另一種調用。

當對象直接作為參數傳給函數時,函數將建立對象的臨時拷貝,這個拷貝過程也將調同拷貝構造函數。

例如

BOOL testfunc(CExample obj);
testfunc(theObjone); //對象直接作為參數。
BOOL testfunc(CExample obj)
{
//針對obj的操作實際上是針對復制后的臨時拷貝進行的
}

還有一種情況,也是與臨時對象有關的

當函數中的局部對象被被返回給函數調者時,也將建立此局部對象的一個臨時拷貝,拷貝構造函數也將被調用

?

CTest func()
{
CTest theTest;
return theTest
}

二、賦值符的重載

下面的代碼與上例相似

int main(int argc, char* argv[])
{
CExample theObjone;
theObjone.Init(40);
CExample theObjthree;
theObjthree.Init(60);
//現在需要一個對象賦值操作,被賦值對象的原內容被清除,并用右邊對象的內容填充。
theObjthree=theObjone;
return 0;
}

也用到了"="號,但與"一、"中的例子并不同,"一、"的例子中,"="在對象聲明語句中,表示初始化。更多時候,這種初始化也可用括號表示。

例如 CExample theObjone(theObjtwo);

而本例子中,"="表示賦值操作。將對象theObjone的內容復制到對象theObjthree;,這其中涉及到對象theObjthree原有內容的丟棄,新內容的復制。

但"="的缺省操作只是將成員變量的值相應復制。舊的值被自然丟棄。

由于對象內包含指針,將造成不良后果:指針的值被丟棄了,但指針指向的內容并未釋放。指針的值被復制了,但指針所指內容并未復制。

因此,包含動態分配成員的類除提供拷貝構造函數外,還應該考慮重載"="賦值操作符號。

類定義變為:

class CExample
{
...
CExample(const CExample&); //拷貝構造函數
CExample& operator = (const CExample&); //賦值符重載
...
};
//賦值操作符重載
CExample & CExample::operator = (const CExample& RightSides)
{
nSize=RightSides.nSize; //復制常規成員
char *temp=new char[nSize]; //復制指針指向的內容
memcpy(temp,RightSides.pBuffer,nSize*sizeof(char));
delete []pBuffer; //刪除原指針指向內容  (將刪除操作放在后面,避免X=X特殊情況下,內容的丟失)
pBuffer=temp;   //建立新指向
return *this
}

三、拷貝構造函數使用賦值運算符重載的代碼。

CExample::CExample(const CExample& RightSides)
{
pBuffer=NULL;
*this=RightSides	 //調用重載后的"="
}
posted on 2008-06-04 15:04 GXW 閱讀(...) 評論(...) 編輯 收藏

轉載于:https://www.cnblogs.com/Fancyboy2004/archive/2008/06/04/1213510.html

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

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

相關文章

SparkSQL 之 Shuffle Join 內核原理及應用深度剖析-Spark商業源碼實戰

本套技術專欄是作者(秦凱新)平時工作的總結和升華,通過從真實商業環境抽取案例進行總結和分享,并給出商業應用的調優建議和集群環境容量規劃等內容,請持續關注本套博客。版權聲明:禁止轉載,歡迎…

Python標準庫之csv(1)

1.Python處理csv文件之csv.writer() import csvdef csv_write(path,data):with open(path,w,encodingutf-8,newline) as f:writer csv.writer(f,dialectexcel)for row in data:writer.writerow(row)return True 調用上面的函數 data [[Name,Height],[Keys,176cm],[HongPing,1…

python自動化測試腳本可以測php嗎_請對比分析一下php的自動化測試與python的自動化測試...

Unit Level Test: Python: doctest, nose PHP: PHPUnit Behaviour Driven Test (Cucumber-style): Python: Lettuce, Behave PHP: Behat Behaviour Driven Test (Spec-style): Python: spec PHP: PHPSpec Acceptance Test (Selenium): Python: 有官方的Selenium binding。 PHP:…

簡單易變的CSS陰影效果

厭倦了在圖片處理軟件上給每張圖片加上邊框修飾?讓CSS幫你一把吧!嘿嘿,看看下面的幾張效果圖,邊框都不是用圖片做的,很方便吧? 文字塊的應用效果 NARROW This is the text that goes in the middle. MEDIUM…

我用代碼來給你們分析一個賺錢的技巧

2019獨角獸企業重金招聘Python工程師標準>>> 賺錢是個俗氣的話題,但又是人人都繞不開的事情。我今天來“科學”地觸碰下這個話題。 談賺錢,就會談到理財、投資,談到炒股。有這樣一個笑話: 問:如何成為百萬富…

idea中自動deployment的步驟

轉載于:https://www.cnblogs.com/littlehb/p/11322666.html

python怎么編輯文件_如何使用python中的方法對文件進行修改文件名

在使用python語言中的方法操作文件時,打開方法可以直接使用open,但是對文件重命名需要調用os模塊中的方法,刪除文件也是工具/原料 python 編輯器 截圖工具 臺式機 方法/步驟 1 進入到python安裝文件目錄,新建txt文件kou.txt2 打開…

球迷必備Euro Cup Mobile 2008 !-dopod touch diamond試用之歐洲杯

歐洲杯從6月8日開始,到現在已經進行了半個多月了。到今天為止已經進入到了尾聲,也到了激戰正酣的時刻!(相信在國足出線無望后大伙的目光都聚集到了歐洲杯上) 但是平時上班忙,晚上也沒法熬夜看球,哥們心理著急呀。白天上…

【工具】switchhost

1.前提 主要功能切換host 2.下載路徑 https://oldj.github.io/SwitchHosts/ 3.使用略(太簡單)轉載于:https://www.cnblogs.com/totoro-cat/p/9987101.html

C# ?. 判斷Null值

有一句代碼: Html.DisplayFor(modelItem > item.SellDate, "RegularDate") RegularDate.cshtml 內容如下: model System.DateTime Model.ToString("yyyy/MM/dd") 目的是將數據庫里的 DateTime 顯示為完整日期,如 2019…

MOSS站點的FORM認證修改小結

項目中,將moss站點修改成form認證的方法,園子里面已經很多了,我就不再重提,其中有1點有些文章沒有提及,但是實際操作中又是比較重要的:在管理中心的web.config中添加roleManager之后,一定要將ht…

python中意外縮進是什么意思_如何處理python中的“意外縮進”?

慕工程0101907 Python在行的開頭使用間距來確定代碼塊何時開始和結束。你可以得到的錯誤是:意外的縮進。這行代碼在開始時比前一行有更多空格,但前一行不是子塊的開頭(例如if / while / for語句)。塊中的所有代碼行必須以完全相同…

HDU 1042 N!(高精度階乘、大數乘法)

N! Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 100274 Accepted Submission(s): 30006 Problem Description Given an integer N(0 ≤ N ≤ 10000), your task is to calculate N!Input One N in one li…

設計模式學習筆記九:原型模式(Prototype Pattern)

1.概述 意圖:我們將已經存在的對象作為原型,用戶可以通過復制這些原型創建新的對象。 使用場合:當一個系統應該獨立于產品的創建、構造和表示時,可以使用原型模式。在原型模式中,產品的創建和初始化…

Centos7上安裝docker

步驟:1、Docker 要求 CentOS 系統的內核版本高于 3.10 ,查看本頁面的前提條件來驗證你的CentOS 版本是否支持 Docker 。通過 uname -r 命令查看你當前的內核版本2、使用 root 權限登錄 Centos。確保 yum 包更新到最新。 (這個可能需要幾分鐘的…

pythonista3安裝stash_Pythonista下stash安裝教程

前言 “StaSh is a serious attempt to implement a Bash-like shell for Pythonista.” StaSh是一個Pythonista環境下的仿shell程序,Sta來自于Pythonista的后三個字母,Sh即shell縮寫。除了能完成shell的基本功能外,最主要的功能還有實現pip安…

通過java類的反射機制獲取類的屬性類型

import java.lang.reflect.Field;import java.lang.reflect.Method; Class<?> clsClass.forName(className);//通過類的名稱反射類//Class<?> cls Object.getClass();Field field cls.getDeclaredField("name");//根據屬性名稱獲取單個屬性if (field…

建立合理的索引提高SQL Server的性能

在應用系統中,尤其在聯機事務處理系統中,對數據查詢及處理速度已成為衡量應用系統成敗的標準。而采用索引來加快數據處理速度也成為廣大數據庫用戶所接受的優化方法。 在良好的數據庫設計基礎上&#xff0c;能有效地使用索引是SQL Server取得高性能的基礎&#xff0c;SQL Serv…

c++ map用法_Python的 5 種高級用法,效率提升沒毛病

原創&#xff1a;機器之心(ID&#xff1a;almosthuman2014)任何編程語言的高級特征通常都是通過大量的使用經驗才發現的。比如你在編寫一個復雜的項目&#xff0c;并在 stackoverflow 上尋找某個問題的答案。然后你突然發現了一個非常優雅的解決方案&#xff0c;它使用了你從不…

非對稱加密算法RSA加密傳輸數據python3源代碼實現

2019獨角獸企業重金招聘Python工程師標準>>> import rsa# RSA 算法規定&#xff1a; # 待加密的字節數不能超過密鑰的長度值除以 8 再減去 11NBIT 4096 CAN_ENCODE_LEN NBIT // 8 - 11 PER_ENCODE_LEN CAN_ENCODE_LEN - (CAN_ENCODE_LEN % 2) PER_DECODE_LEN CA…