文章目錄
- 析構函數
- 1.析構函數的定義:
- 2.析構函數的語法:
- 3.析構函數的特性:
- 拷貝構造函數
- 1.拷貝構造函數的定義:
- 2.拷貝構造函數的語法
- 3.拷貝構造函數的特性
- (1)拷貝構造函數是構造函數的一個重載形式**(這個其實也很好理解,由于構造函數實現的是對對象的初始化,而拷貝構造也是對對象的初始化,只不過需要把值進行拷貝,然后實現初始化,所以它們的功能是相似的,但它們的參數不同,所以它們構成函數的重載)**
- (2)拷貝構造參數只能有一個,并且這個參數只能是類的類型對象的引用,用傳值的方式,編譯器會直接報錯,因為傳值調用會引發拷貝構造函數的無窮遞歸。
- (3)如果沒有自定義一拷貝構造函數編譯器會自動生成一個默認的拷貝構造函數
- (4)淺拷貝和深拷貝
- 總結:
析構函數
1.析構函數的定義:
析構函數是為了完成清理工作的,但不是對對象本身的清理,局部對象的清理是由編譯器自動完成的,析構函數是對對象中的資源的清理。
2.析構函數的語法:
~+類名()
class Stack
{
public://析構函數不需要傳參過來,因為會有this指針傳過來~Stack()//析構函數:~+類名(){free(_a);_a = nullptr;_size = _capacity = 0;}private:int* _a;size_t _size;size_t _capacity;
};
3.析構函數的特性:
(1)析構函數無參數無返回值
(2)一個類只有一個析構函數,若沒有自定義析構函數,那么編譯器會自動生成析構函數,注意:析構函數是不能重載的。(這個為挺好理解的,如果你有多個函數都能實現清理的功能,由于析構函數是編譯器自動調用的,那么編譯器就不知道要調用那個函數來清理對象所占的資源了)
(3)對象的生命周期結束時,編譯器自動調用析構函數。
(4)編譯器自動生成的析構函數,對自定義成員變量會去調用它的析構函數, 但編譯器自動生成的構造函數和析構函數不會去初始化和清理內置類型/基本類型(int/char)
下面的代碼如果輸出~Time()這個字符串,就表示編譯器自動生成的析構函數會去調用自定義類型的析構函數
class Time
{
public:~Time(){cout << "~Time()" << endl;}
private:int _hour;int _minute;int _second;
};
class Date
{
private:// 基本類型(內置類型)int _year = 1970;int _month = 1;int _day = 1;// 自定義類型Time _t;
};
int main()
{Date d;return 0;
}
拷貝構造函數
1.拷貝構造函數的定義:
拷貝構造,顧名思義就是對一個對象的拷貝唄。
2.拷貝構造函數的語法
類名+(參數)
Date(const Date& d)
{//防止下面賦值操作寫錯,給d去掉可修改的權限_year = d._year;_month = d._month;_day = d._day;
}
3.拷貝構造函數的特性
(1)拷貝構造函數是構造函數的一個重載形式**(這個其實也很好理解,由于構造函數實現的是對對象的初始化,而拷貝構造也是對對象的初始化,只不過需要把值進行拷貝,然后實現初始化,所以它們的功能是相似的,但它們的參數不同,所以它們構成函數的重載)**
(2)拷貝構造參數只能有一個,并且這個參數只能是類的類型對象的引用,用傳值的方式,編譯器會直接報錯,因為傳值調用會引發拷貝構造函數的無窮遞歸。
(3)如果沒有自定義一拷貝構造函數編譯器會自動生成一個默認的拷貝構造函數
(4)淺拷貝和深拷貝
下面來判斷一段代碼,看看這個代碼能否正常運行
typedef int DataType;
class Stack
{
public:Stack(size_t capacity = 10){_array = (DataType*)malloc(capacity * sizeof(DataType));if (nullptr == _array){perror("malloc申請空間失敗");return;}_size = 0;_capacity = capacity;}void Push(const DataType& data){// CheckCapacity();_array[_size] = data;_size++;}~Stack(){if (_array){free(_array);_array = nullptr;_capacity = 0;_size = 0;}}
private:DataType* _array;size_t _size;size_t _capacity;
};
int main()
{Stack s1;s1.Push(1);s1.Push(2);s1.Push(3);s1.Push(4);Stack s2(s1);return 0;
}
代碼直接崩了,這是因為什么呢?容我慢慢道來
注意:當類沒有涉及空間資源的開辟時,構造函數可自己寫也可不寫,一旦涉及資源的開辟時,構造函數必須自己寫,防止出現淺拷貝問題。
總結:
今天總結了析構函數和拷貝構造函數。