復制構造函數(copy constructor)是一種特殊構造函數,具有單個形參,該形參(常用const修飾)是對該類類型的引用。當定義一個新對象並用一個同類型的對象對它進行初始化時,將顯式使用復制構造函數。當將該類型的對象傳遞給函數或從函數返回該類型的對象時,將隱式使用復制構造函數。
析構函數(destructor)是構造函數的互補:當對象超出作用域或動態分配的對象被刪除時,將自己應用析構函數。析構函數可用於釋放對象時構造或在對象的生命期中所獲取的資源。不管類是否定義了自己的析構函數,編譯器都自動執行類中非static數據成員的析構函數。
賦值操作符(assignment operator)可以通過指定不同類型的右操作數而重載。右操作數為類類型的版本比較特殊:如果我們沒有編寫這種版本,編譯器將為我們合成一個。
復制構造函數、賦值操作符和析構函數總稱為復制控制(copy control)。編譯器自動實現這些操作,但類也可以定義自己的版本。
有一種特殊常見的情況需要類定義自己的復制控制成員的:類具有指針成員。
13.1 復制構造函數
只有單個形參,而且該形參是對本類類型對象的引用(常用const修飾),這樣的構造函數稱為復制構造函數。與默認構造函數一樣,復制構造函數可由編譯器隱式調用。復制構造函數可用於:
根據一個同類型的對象顯式或隱式初始化一個對象。
復制一個對象,將它作為實參傳遞給一個函數。
從函數返回時復制一個對象。
初始化順序容器中的元素。
根據元素初始化式列表初始化數組元素。
1. 對象的定義形式
C++支持兩種初始化形式:直接初始化和復制初始化。復制初始化使用=符號,而直接初始化將初始化式放在圓括號中。
當用於類類型對象時,初始化的復制形式和直接形式有所不同:直接初始化直接調用與實參匹配的構造函數,復制初始化總是調用復制構造函數。復制初始化首先使用指定構造函數創建一個臨時對象,然後用復制構造函數將那個臨時對象復制到正在創建的對象。
StaticClass cs1();
StaticClass cs2 = StaticClass();
對於類類型對象,只有指定單個實參或顯式創建一個臨時對象用於復制時,才使用復制初始化。
由於不能復制IO類型的對象,所以不能對那些類型的對象使用復制初始化。
2. 形參與返回值
當形參為非引用類型的時候,將復制實參的值。類似地,以非引用類型做返回值時,將返回return語句中的值的副本。
當形參或返回值為類類型時,由復制構造函數進行復制。
3. 初始化容器元素
復制構造函數可用於初始化順序容器中的元素。例如,可以用表示容量的單個形參來初始化容器。容器的這種構造方式使用了默認構造函數和復制構造函數。
vector<string> vec(5);
作為一般規則,除非你想使用容器元素的默認初始值,更有效的辦法是,分配一個空容器並將已知元素的值加入容器。
4. 構造函數和數組元素
如果沒有為類類型數組提供元素初始化式,則將用默認構造函數初始化每個元素。然而,如果使用常規的花括號括住的數組初始化列表來提供顯式元素初始化式,則使用復制初始化來初始化每個元素。根據指定值創建適當類型的元素,然後用復制構造函數將該值復制到相應元素。
class Class5
{
public:
int k;
Class5(int i): k(i){}
};
Class5 arr[4] = {1, 2, 3, Class5(4)};
摘自 xufei96的專欄