在很多時候,當寫了初始化,動態(tài)開辟的,需要寫銷毀函數(shù),寫了銷毀函數(shù)之后,但是卻忘記了調(diào)用這些函數(shù),忘記調(diào)用初始化函數(shù)還好,編譯器會報錯,但是如果是忘記調(diào)用銷毀函數(shù),那么編譯器是不會報錯,但是不能說這個程序就沒錯哦了,反而有很大的問題,存在內(nèi)存泄漏的問題,如和解決這樣問題?這也是本文重點。C++增加了類的6個默認成員函數(shù),本文先分享構(gòu)造函數(shù)和析構(gòu)函數(shù)。
構(gòu)造函數(shù)–主要完成初始化工作,
析構(gòu)函數(shù)–主要完成清理工作
一、前言
在很多時候,當寫了初始化,動態(tài)開辟的,需要寫銷毀函數(shù),寫了銷毀函數(shù)之后,但是卻忘記了調(diào)用這些函數(shù),忘記調(diào)用初始化函數(shù)還好,編譯器會報錯,但是如果是忘記調(diào)用銷毀函數(shù),那么編譯器是不會報錯,但是不能說這個程序就沒錯哦了,反而有很大的問題,存在內(nèi)存泄漏的問題,如和解決這樣問題?這也是本文重點。C++增加了類的6個默認成員函數(shù),本文先分享構(gòu)造函數(shù)和析構(gòu)函數(shù)。
構(gòu)造函數(shù)–主要完成初始化工作
析構(gòu)函數(shù)–主要完成清理工作
二、構(gòu)造函數(shù)
構(gòu)造函數(shù)是特殊的成員函數(shù),雖然它的名字叫構(gòu)造函數(shù),但是它的主要任務不是開空間創(chuàng)建對象,而是初始化對象
特性:
1、函數(shù)名和類名相同。
如:類名Stack,那么構(gòu)造函數(shù)的函數(shù),名也為Stack
2、無返回值(也不需要void)。
3、對象實例化編譯器自動調(diào)用對應的構(gòu)造函數(shù)。
對象在定義之后就會調(diào)用它的默認構(gòu)造函數(shù)
4、構(gòu)造函數(shù)可以重載。
(構(gòu)造函數(shù)雖然沒有返回值,但是可以有參數(shù))
5、如果類中沒有顯式定義構(gòu)造函數(shù),則c++編譯器會自動生成一個無參的默認構(gòu)造函數(shù),一旦用戶顯式定義,編譯器不再默認生成。
以日期類帶大家了解
#include<iostream>
using namespace std;
class Date
{
public:
Date(int year=2022, int month=4, int day=24)
{
_year = year;
_month = month;
_day = day;
}
void Print()
{
cout << _year << '-' << _month << '-' << _day << endl;
}
int _year;
int _month;
int _day;
};
int main()
{
Date d1;
d1.Print();
return 0;
}
在對象定義之后并沒有顯式調(diào)用構(gòu)造函數(shù),但是在打印這個對象的時候卻是有內(nèi)容的,因為在對象定義時編譯器自動調(diào)用它的默認構(gòu)造函數(shù),(默認構(gòu)造函數(shù)是構(gòu)造函數(shù)參數(shù)列表全缺?。?br>
構(gòu)造函數(shù)是沒有返回值的,且它的函數(shù)名與類名相同,它還能有參數(shù)也可以沒有參數(shù)
無參和參數(shù)列表全給缺省值這兩個函數(shù)在同一個類中只能出現(xiàn)其中之一
構(gòu)造函數(shù)支持重載
對重載構(gòu)造函數(shù)的調(diào)用
當構(gòu)造函數(shù)重載,一個構(gòu)造函數(shù)無參數(shù),一個構(gòu)造函數(shù)參數(shù)列表全給缺省值,對象定義之后自動調(diào)用它的默認構(gòu)造函數(shù),編譯器不知道調(diào)用誰,此時會發(fā)生調(diào)用歧義,所以得出,構(gòu)造函數(shù)無參數(shù)和參數(shù)列表全給缺省值這兩個在一個類中只能出現(xiàn)其中之一,一個出現(xiàn)另一個就不能出現(xiàn)。
構(gòu)造函數(shù)參數(shù)列表全為缺省參數(shù)或者無參時,在對象定以之后會自動調(diào)用,那么如果構(gòu)造函數(shù)參數(shù)列表不權(quán)威缺省參數(shù)或者不為缺省參數(shù)時,應當如何?
當構(gòu)造函數(shù)參數(shù)列表不全是缺省值時
此時會顯示d1這個對象并不存在默認構(gòu)造函數(shù),在定義之后不能自動調(diào)用它的構(gòu)造函數(shù)了
那么在定義對象時就不能簡簡單單的定義了 而是對象+參數(shù)列表
,此時編譯器才會自動調(diào)用構(gòu)造函數(shù)
但是就算構(gòu)造函數(shù)參數(shù)列表全為缺省參數(shù)或者無參,也不能像這樣
此時編譯器并不知道這個對象是聲明還是定義
Data d1;//當構(gòu)造函數(shù)參數(shù)列表全是缺省值時,編譯器在對象實例化時才會默認自動調(diào)用構(gòu)造函數(shù),不然的話就需要對其傳參
對象+參數(shù)列表,此時就會自動調(diào)用構(gòu)造函數(shù)
構(gòu)造函數(shù):要么是無參、要么是全缺省、要么是沒有顯式寫編譯器會自動生成默認構(gòu)造函數(shù)(不傳參就可以調(diào)用的函數(shù)就是默認構(gòu)造函數(shù))
構(gòu)造函數(shù)替代了Init(初始化),可以不用調(diào)用Init也對這個對象初始化了,這樣也就解決了因沒有調(diào)用初始化帶來的錯誤,
構(gòu)造函數(shù)是給對象初始化,在對象定義時自動調(diào)用
但是如果當類中沒有定義構(gòu)造函數(shù)時,應該如何處理?
編譯器會自動生成構(gòu)造函數(shù),但是自動生成的構(gòu)造函數(shù),編譯器并沒用對類中的內(nèi)置類型成員初始化
但是也有一些編譯器會將其內(nèi)置類型成員初始化為0,不過大多數(shù)是不會處理的內(nèi)置類型:(int/double/指針等等)
自定義類型:自己定義的/struct/class等等定義的類型
編譯器自動生成構(gòu)造函數(shù)也并不是什么都不做,當我們在類中,不顯式寫構(gòu)造函數(shù),編譯器會默認生成構(gòu)造函數(shù),類中內(nèi)置類型不做處理,自定義類型會調(diào)用它的默認構(gòu)造函數(shù)
以日期類中字自定義一個棧對象來看
#include<iostream>
using namespace std;
class Stack
{
public:
Stack(int capacity = 4)
{
_a = (int*)malloc(sizeof(int) * capacity);
if (_a == nullptr)
{
perror("malloc fail\n");
return;
}
_top = 0;
_capacity = capacity;
cout << "_top" << ' ' << "_capacity" << endl;
}
int _capacity;
int* _a;
int _top;
};
class Data
{
public:
void Print()
{
cout << _year << '-' << _month << '-' << _day << endl;
}
int _year;
int _month;
int _day;
Stack _st;
};
int main()
{
Data d1;
d1.Print();
return 0;
}
可以發(fā)現(xiàn),自動生成了默認構(gòu)造函數(shù),這里類的內(nèi)置類型成員被處理為0了,其實大多數(shù)編譯器是不會對類的內(nèi)置類型成員進行處理
當類中沒有構(gòu)造函數(shù)時,編譯器會默認自動生成構(gòu)造函數(shù) 但是并不會對類的內(nèi)置類型成員做處理(初始化)
當類中有自定義類型成員時,編譯器會默認自動調(diào)用自定義類型它的構(gòu)造函數(shù),
同時有些編譯器也會將類的內(nèi)置類型成員初始化為0,但是這只是有些編譯器,并不是全部那么哪種類可以讓編譯器默認自動生成構(gòu)造函數(shù)哪些不能? 一般情況下,類只要有內(nèi)置類型成員,理論上不能讓編譯器默認自動生成構(gòu)造函數(shù)
一般情況下,如果類成員全是自定義類型成員,可以考慮讓編譯器默認自動生成構(gòu)造函數(shù)(兩個棧實現(xiàn)隊列)
所以在c++11標準發(fā)布,也算是為其做了一些補丁
在類中內(nèi)置類型成員在聲明的時候給缺省值,此時編譯器默認自動生成構(gòu)造函數(shù)時
這些內(nèi)置類型成員不再是隨機值,而是這些缺省值
#include<iostream>
using namespace std;
class Stack
{
public:
Stack(int capacity = 4)
{
_a = (int*)malloc(sizeof(int) * capacity);
if (_a == nullptr)
{
perror("malloc fail\n");
return;
}
_top = 0;
_capacity = capacity;
cout << "_top" << ' ' << "_capacity" << endl;
}
int _capacity;
int* _a;
int _top;
};
class Data
{
public:
void Print()
{
cout << _year << '-' << _month << '-' << _day << endl;
}
//可以在聲明時給其缺省值
int _year = 1;
int _month = 1;
int _day = 1;
Stack _st;
};
int main()
{
Data d1;
d1.Print();
return 0;
}
類中沒有定義構(gòu)造函數(shù),編譯器會自動生成默認構(gòu)造函數(shù),再自動調(diào)用生成的構(gòu)造函數(shù),然后此時對類的內(nèi)置類型成員給缺省值,此時就相當于是對類的內(nèi)置類型成員處理
- 類中沒有顯式定義構(gòu)造函數(shù),編譯器會自動生成一個無參的默認構(gòu)造函數(shù)
- 內(nèi)置類型成員不做處理(a 有些編譯器會處理 b.c++11標準對其縫補,聲明可以給缺省值初始化)
- 自定義類型成員,會自動去調(diào)用它的構(gòu)造函數(shù)
關(guān)于構(gòu)造函數(shù)
總結(jié):
- 一般情況下,構(gòu)造函數(shù)都需要我們自己顯式寫
- 內(nèi)置類型成員都有缺省值,且這些缺省值初始化符合自己要求,不用顯式寫構(gòu)造函數(shù)
- 類中成員全是自定義類型,且這些類型都定義默認構(gòu)造函數(shù),不用顯式寫構(gòu)造函數(shù)
三、析構(gòu)函數(shù)
析構(gòu)函數(shù)與構(gòu)造函數(shù)功能相反,它是對資源的清理,相當于銷毀函數(shù),析構(gòu)函數(shù)是在定義的對象生命周期結(jié)束時自動調(diào)用析構(gòu)函數(shù),完成對資源的清理,這樣就算忘了調(diào)用銷毀函數(shù)也不會造成內(nèi)存泄漏了
析構(gòu)函數(shù)特性:
- 析構(gòu)函數(shù)名是在類名前加 ~
- 無參數(shù),無返回值
- 一個類只能有一個析構(gòu)函數(shù)(不能重載,析構(gòu)函數(shù)無參數(shù)),
若是未顯式定義,系統(tǒng)會自動生成默認析構(gòu)函數(shù)。- 對象生命周期結(jié)束時,編譯器會自動調(diào)用析構(gòu)函數(shù)
5.若是未顯式定義,系統(tǒng)會自動生成默認析構(gòu)函數(shù)(生成的默認析構(gòu)函數(shù)和自動生成的構(gòu)造函數(shù)類似(a.內(nèi)置類型成員不做處理 b.自定義類型會調(diào)用它的析構(gòu)函數(shù)))
以棧為例
#include<iostream>
using namespace std;
class Stack
{
public:
Stack(int capacity = 4)
{
_a = (int*)malloc(sizeof(int) * capacity);
if (_a == nullptr)
{
perror("malloc fail\n");
return;
}
_top = 0;
_capacity = capacity;
cout << "_top=" <<_top<< ' ' << "_capacity="<<_capacity << endl;
}
~Stack()
{
free(_a);
_a = nullptr;
_top = 0;
_capacity = 0;
cout << "_top=" << _top << ' ' << "_capacity=" << _capacity << endl;
}
int _capacity;
int* _a;
int _top;
};
int main()
{
Stack st1;
return 0;
}
調(diào)試轉(zhuǎn)到反匯編,可以發(fā)現(xiàn),是在對象生命周期結(jié)束,自動調(diào)用析構(gòu)函數(shù)
類中沒有顯式寫析構(gòu)函數(shù),編譯器會自動生成一個默認析構(gòu)函數(shù),其實和構(gòu)造函數(shù)差不多
析構(gòu)函數(shù)總結(jié)
一般情況下,如果對類成員寫的是靜態(tài)的,那么就不用寫析構(gòu)函數(shù)。有動態(tài)申請資源的,就需要顯式寫析構(gòu)函數(shù)釋放資源。文章來源:http://www.zghlxwxcb.cn/news/detail-427169.html
類中成員沒有動態(tài)申請資源,不需要寫析構(gòu)函數(shù)
類中需要釋放資源的成員都是自定義類型,不需要寫析構(gòu)函數(shù)文章來源地址http://www.zghlxwxcb.cn/news/detail-427169.html
到了這里,關(guān)于C++篇----構(gòu)造函數(shù)和析構(gòu)函數(shù)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!