拷貝建構函式和賦值構造

2021-10-20 11:41:27 字數 3181 閱讀 4578

為什麼空類可以建立物件呢?

複製建構函式的引數可以是 const 引用,也可以是非 const 引用。 一般使用前者,這樣既能以常量物件(初始化後值不能改變的物件)作為引數,也能以非常量物件作為引數去初始化其他物件。乙個類中寫兩個複製建構函式,乙個的引數是 const 引用,另乙個的引數是非 const 引用,也是可以的。

造函式的最常見形式如下:

classname (const classname &obj)

示例**如下:

#include using namespace std;

class empty

;void main()

讓我們先看看這個例子。既然都沒有建構函式,怎麼實現物件obj1的構建呢?

哦,經過大腦的迴旋式搜尋,憶得有一本書上說過,當使用者定義乙個空類(如上)時,編譯器就會為這個類預設生成六個方法。

既然是編譯器預設完成的工作,那我們只要知道具體是那些方法,其餘就學習編譯器的原理了。

那麼,編譯器生成了那六個方法:示例**如下:

class empty

;

ok,這就是預設生成的那六個方法。其中前四個是經常談及到的,也是平常定義乙個類時,尤其要慎重考慮的。

到這裡,也許有人還看出了點問題。那就是為什麼空類的大小是1呢??呵呵~~編譯器搞的鬼?其實也不是隨隨便便搞的鬼,我們說:存在即是合理的!這樣做肯定有它的道理。

好啦,如果sizeof(empty) == 0,那麼我們如何區分陣列中的十個元素呢??你想想這是不是狹隘的表現嗎?

所以說,為了更完善,更健壯,更偉大。編譯器插入這個位元組,是為了在使用這個類定義多個物件的時候能保證每個物件有自己的位址。

empty *pa1, *pa2;

pa1 = new empty();

pa2 = new empty();

// ..

if (pa1 == pa2) // 如果不分配記憶體,這個比較就會失去意義

如果不分配記憶體,如上的**會不成立!

1)拷貝建構函式是乙個物件初始化一塊記憶體區域,這塊記憶體就是新物件的記憶體區,而賦值函式是對於乙個已經被初始化的物件來進行賦值操作。

class  a;  

a a;

a b=a; //呼叫拷貝建構函式(b不存在)

a c(a) ; //呼叫拷貝建構函式

/****/

class a;

a a;

a b;

b = a ; //呼叫賦值函式(b存在)

拷貝建構函式和賦值運算子的行為比較相似,都是將乙個物件的值複製給另乙個物件;但是其結果卻有些不同,拷貝建構函式使用傳入物件的值生成乙個新的物件的例項,而賦值運算子是將物件的值複製給乙個已經存在的例項。這種區別從兩者的名字也可以很輕易的分辨出來,拷貝建構函式也是一種建構函式,那麼它的功能就是建立乙個新的物件例項;賦值運算子是執行某種運算,將乙個物件的值複製給另乙個物件(已經存在的)。呼叫的是拷貝建構函式還是賦值運算子,主要是看是否有新的物件例項產生。如果產生了新的物件例項,那呼叫的就是拷貝建構函式;如果沒有,那就是對已有的物件賦值,呼叫的是賦值運算子

呼叫拷貝建構函式主要有以下場景:

**如下:

class person

person(const person& p)

person& operator=(const person& p)

private:

int age;

string name;

};void f(person p)

person f1()

int main()

上面**中定義了乙個類person,顯式的定義了拷貝建構函式和賦值運算子。然後定義了兩個函式:f,以值的方式參傳入person物件;f1,以值的方式返回person物件。在main中模擬了5中場景,測試呼叫的是拷貝建構函式還是賦值運算子。執行結果如下:

分析如下:

這是雖然使用了"=",但是實際上使用物件p來建立乙個新的物件p1。也就是產生了新的物件,所以呼叫的是拷貝建構函式。

首先宣告乙個物件p2,然後使用賦值運算子"=",將p的值複製給p2,顯然是呼叫賦值運算子,為乙個已經存在的物件賦值 。

以值傳遞的方式將物件p2傳入函式f內,呼叫拷貝建構函式構建乙個函式f可用的實參。

這條語句拷貝建構函式和賦值運算子都呼叫了。函式f1以值的方式返回乙個person物件,在返回時會呼叫拷貝建構函式建立乙個臨時物件tmp作為返回值;返回後呼叫賦值運算子將臨時物件tmp賦值給p2.

按照4的解釋,應該是首先呼叫拷貝建構函式建立臨時物件;然後再呼叫拷貝建構函式使用剛才建立的臨時物件建立新的物件p3,也就是會呼叫兩次拷貝建構函式。不過,編譯器也沒有那麼傻,應該是直接呼叫拷貝建構函式使用返回值建立了物件p3。

舉個例子:

#include using namespace std;

class demo

//拷貝建構函式

demo(const demo &d) : num(new int(*d.num))

~demo()

private:

int *num;

};demo get_demo() //demo b;return b; }

int main()

construct!

copy construct!   //return b;呼叫 

class destruct!:0x%x0x7fff87509860  //b的析構

copy construct!   //a=x構造

class destruct!:0x%x0x7fff875098a0  //臨時變數析構

class destruct!:0x%x0x7fff87509898  //a的析構

詳細參考此文:

拷貝建構函式和賦值建構函式

class cmystring 賦值建構函式 cmystring cmystring operator const cmystring str 新分配記憶體,將str的m pdata記憶體拷貝到m pdata中 m pdata new char strlen str.m pdata 1 strcpy...

拷貝建構函式和賦值建構函式

拷貝構造是確確實實構造乙個新的物件,並給新物件的私有成員賦上引數物件的私有成員的值,新構造的物件和引數物件位址是不一樣的,所以如果該類中有乙個私有成員是指向堆中某一塊記憶體,如果僅僅對該私有成員進行淺拷貝,那麼會出現多個指標指向堆中同一塊記憶體,這是會出現問題,如果那塊記憶體被釋放了,就會出現其他指...

建構函式 拷貝建構函式 賦值建構函式

class和struct很大乙個區別在於,c除了成員的訪問控制許可權,struct中的成員預設是public,而class中的field預設是private class還有乙個special的地方是它有建構函式 constructor。建構函式是class中的一員,和成員變數 其他成員函式一起構成乙...