C++ 复制控制之复制构造函数
?
7月26日更新:
過了這么長的時間回過頭來看,發現文章中有幾個點說錯(用紅字標出):
?
《《=========================================================================》》
?
C++類用三個特殊的成員函數:復制構造函數、賦值操作符和析構函數 來決定類對象之間的初始化或賦值時發生什么。所謂的“復制控制”即通過這三個成員函數控制對象復制的過程。本篇文章將介紹復制構造函數。
- 復制構造函數
復制構造函數是什么
?? 復制構造函數首先是一個構造函數,它同所有其他的構造函數一樣與類同名,沒有返回值。它有一個唯一的參數(錯誤),是該類類型的引用(一般將它聲明為const,源于用于賦值的對象一般不用改變它本身的值)。于是復制構造函數的原型為:
class BOOK { public:BOOK(const BOOK& rhs); //構造函數一BOOK(string &name,float price = 0):_bookName(name),_price(price){}; //構造函數二BOOK():_price(0),_bookName(""){}; //構造函數三private: float _price ; string _bookName;//.... };
?
什么時候被調用
?? 復制構造函數在需要復制類對象的時候被調用,這些調用情況可以總結為:
當定義一個新對象并用一個同類型的對象對它進行初始化的時候,將顯式使用復制構造函數,如:
BOOK book1; BOOK book2(book1);當將該類型的對象傳遞給函數或從函數返回該類型的對象時,將隱式地調用復制構造函數。
? ?如:
vector<string> svec(5);?
編譯器首先調用string類默認構造函數創建一個臨時值,再用復制構造函數將臨時值復制到每一個元素。
如:
BOOK books[]={string("book1"),string("book2"),string("book3"),BOOK() };?
book數組的前三個元素將調用構造函數二進行隱式類型轉換(C++隱式類型轉換),然后調用復制構造函數進行數組元素的復制。如果類禁止隱式類型轉換(構造函數使用了explicit聲明),或希望不指定實參或多個實參,需要使用完整的構造函數語法,如數組最后一個元素的初始化。
?
如果沒有為類聲明復制構造函數會怎樣
????? 如果你沒有聲明一個復制構造函數,那么編譯器會給聲明一個。實際上,如果你自己沒有聲明,編譯器會為類聲明一個復制構造函數 ,一個賦值操作符以及一個析構函數,此外如果你沒有聲明任何構造函數的話,編譯器也會為你聲明一個合成默認構造函數。(錯誤)所有這些編譯器自動生成的類成員函數皆為pubilc 且 inline。(這部分內容可以參考《Effective C++》條款05)編譯器創建的復制構造函數單純地將來源對象的每一個非static成員拷貝到目標對象,這在很多時候是不能滿足類需求的,特別是類中含有指針時,這時候就需要我們自己來寫復制控制的三個特殊成員函數了。
?
編譯器合成的復制構造函數做了什么
合成復制構造函數的行為是:對每一個非static成員進行逐個成員初始化。成員類型不同,初始化方式不一樣:
內置類型(如int):直接復制值。
類類型:調用該類的復制構造函數進行復制。
數組:這個比較特殊,因為我們知道一般不能復制數組,但在類中,復制數組時合成復制構造函數將復制數組的每一個值。
另外,合成復制構造函數對類數據成員的初始化都是放在構造函數初始化列表中進行的。
?
禁止復制
?
????? 如果我們想禁止某個類的復制行為,我們當然不會想去定義一個復制構造函數,然而編譯器卻會自動為我們定義一個,那么到底該如何阻止一個類的復制行為呢?
????? 我們可以將復制構造函數定義為private,不允許用戶代碼復制該類類型的對象,若進行復制將在編譯時發生錯誤。然而類的友元和成員仍可以進行復制,解決辦法是我們可以聲明一個private復制構造函數卻不進行定義,類成員或友元進行復制嘗試時,將在程序運行時發生錯誤。
總結:為駁回編譯器自動提供的機能,可將相應的成員函數聲明為private并且不予實現。(具體可參考《Effective C++》條款06 若不想使用編譯器自動生成的函數,就該明確拒絕)
?
轉載于:https://www.cnblogs.com/QG-whz/p/4485574.html
總結
以上是生活随笔為你收集整理的C++ 复制控制之复制构造函数的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: hdu 2275 Kiki Littl
- 下一篇: html5 标签