C 基礎學習9 建構函式和析構函式

2022-07-07 20:06:11 字數 2613 閱讀 8967

1.  建構函式用來對類物件進行初始化,它完成對記憶體空間的申請、賦初值等工作。 

2.  析構函式主要是用來做清理工作的。

補充:函式名或變數名前面有"::"但是沒有類名,說明這是全域性變數或公共函式,並且不屬於任何命名空間。僅此而已。

1、建構函式和析構函式為什麼沒有返回值?

建構函式和析構函式是兩個非常特殊的函式:它們沒有返回值。這與返回值為void的函式顯然不同,後者雖然也不返回任何值,但還可以讓它做點別的事情,而建構函式和析構函式則不允許。在程式中建立和消除乙個物件的行為非常特殊,就像出生和死亡,而且總是由編譯器來呼叫這些函式以確保它們被執行。如果它們有返回值,要麼編譯器必須知道如何處理返回值,要麼就只能由客戶程式設計師自己來顯式的呼叫建構函式與析構函式,這樣一來,安全性就被人破壞了。另外,析構函式不帶任何引數,因為析構不需任何選項。

如果允許建構函式有返回值,在某此情況下,會引起歧義。如下兩個例子

class c

c(int i): x(i)

private:

int x;

};如果c的建構函式可以有返回值,比如int:int c():x(0) //1表示構造成功,0表示失敗

那麼下列**會發生什麼事呢?

c c = c();  //此時c.x == 1!!!

很明顯,c()呼叫了c的無引數建構函式。該建構函式返回int值1。恰好c有乙個但引數建構函式c(int i)。於是,混亂來了。按照c++的規定,c c = c();是用預設建構函式建立乙個臨時物件,並用這個臨時物件初始化c。此時,c.x的值應該是0。但是,如果c::c()有返回值,並且返回了1(為了表示成功),則c++會用1去初始化c,即呼叫但引數建構函式c::c(int i)。得到的c.x便會是1。於是,語義產生了歧義。使得c++原本已經非常複雜的語法,進一步混亂不堪。

建構函式的呼叫之所以不設返回值,是因為建構函式的特殊性決定的。從基本語義角度來講,建構函式返回的應當是所構造的物件。否則,我們將無法使用臨時物件:

void f(int a)   //(1)

void f(const c& a) //(2)

f(c()); //(3),究竟呼叫誰?

對於(3),我們希望呼叫的是(2),但如果c::c()有int型別的返回值,那麼究竟是調(1)好呢,還是呼叫(2)好呢。於是,我們的過載體系,乃至整個的語法體系都會崩潰。

這裡的核心是表示式的型別。目前,表示式c()的型別是類c。但如果c::c()有返回型別r,那麼表示式c()的型別應當是r,而不是c,於是便會引發上述的型別問題。

2、顯式呼叫建構函式和析構函式

#include

using namespace std;

class myclass

~myclass()

};int main()

結果:constructors

destructors    //這個是顯示呼叫的析構函式

destructors    //這個是delete呼叫的析構函式

這有什麼用?有時候,在物件的生命週期結束前,想先結束這個物件的時候就會派上用場了。直接呼叫析構函式並不釋放物件所在的記憶體。

由此想到的: 

new的時候,其實做了三件事,一是:呼叫::operator new分配所需記憶體。二是:呼叫建構函式。三是:返回指向新分配並構造的物件的指標。

delete的時候,做了兩件事,一是:呼叫析構函式,二是:呼叫::operator delete釋放記憶體。

所以推測建構函式也是可以顯式呼叫的。做個實驗:

int main()

編譯pmyclass->myclass()出錯:

error c2273: 'function-style cast' : illegal as right side of '->'operator

它以為myclass是這個型別。

解決辦法有兩個:

第一:pmyclass->myclass::myclass();

第二:new(pmyclass) myclass();

第二種用法涉及c++ placement new 的用法。參考:

顯示呼叫建構函式有什麼用?

有時候,你可能由於效率考慮要用到malloc去給類物件分配記憶體,因為malloc是不呼叫建構函式的,所以這個時候會派上用場了。

另外下面也是可以的,雖然內建型別沒有建構函式。

int* i = (int*)malloc(sizeof(int));

new (i) int();

3、拷貝(複製)建構函式為什麼不能用值傳遞

當你嘗試著把拷貝建構函式寫成值傳遞的時候,會發現編譯都通不過,錯誤資訊如下:

error: invalid constructor; you probably meant 's (const s&)' (大致意思是:無效的建構函式,你應該寫成。。。)

當編譯錯誤的時候你就開始糾結了,為什麼拷貝建構函式一定要使用引用傳遞呢,我上網查詢了許多資料,大家的意思基本上都是說如果用值傳遞的話可能會產生死迴圈。編譯器可能基於這樣的原因不允許出現值傳遞的拷貝建構函式,也有可能是c++標準是這樣規定的。

如果真是產生死迴圈這個原因的話,應該是這樣子的:

class s

s(const s st) //拷貝建構函式

private:

int a;

};int main()

C 學習 建構函式和析構函式

當建立物件的時候,這個物件應該有乙個初始狀態 當物件銷毀之前應該銷毀自己建立的一些資料。c 中的解決方案,建構函式和析構函式,這兩個函式將會被編譯器自動呼叫,完成物件初始化和物件清理工作 不管有沒有我們有沒有提供初始化操作和清理操作,編譯器也會增加預設的操作,只是這個預設初始化操作不會做任何事,所以...

C 基礎 (建構函式 析構函式)

constructor中文解釋為建構函式,是一種特殊的函式 constructor function 不應理解為構造器 constructor保證了物件只要被建立出來就會被初始化 constructor與類的名字是相同的 大小寫都一模一樣 constructor沒有任何返回型別 constructo...

c 基礎學習 析構函式 拷貝建構函式

字串函式 string類是c 提供的字串類,其主要功能是對字串進行操作。string類定義的變數稱為字串物件,該物件可以直接用字串常量賦值,也可呼叫string類中定義的成員函式。常型別是指使用型別修飾符const說明的型別,常型別的變數或物件的值不能被更新。c 中引入const的目的是為了取代巨集...