天天看點

拷貝構造函數和指派運算符重載

拷貝構造函數 :

1概念

拷貝構造函數隻有單個形參,該形參是對本類類型對象的引用(常用const 修飾),

使用已存在的類類型的對象建立新對象時,編譯器自動調用該函數。

eg:

假如 Claa A{

public:A(const A& a){}

private :

int a;},

A a ,

A b(a);

2 特征

1 隻有一個參數: 引用傳參,傳值方式将會無限遞歸(Why)

傳值無限遞歸原因:傳值時拷貝構造函數的形參将會拷貝傳來的值,也是一個拷貝構造同時也是一個拷貝相當于A b(a);因為類并沒有正确實作引用,是以将在形參接收這裡無限遞歸下去。

另外,寫成傳值編譯器将會報錯

2 拷貝構造函數是構造函數的一個重載形式,(言下之意,構造函數還有别的函數重載形式)

3 若未進行顯式地定義拷貝構造函數,編譯器将隐式地生成一個拷貝構造函數,。今天我來補充一下,另一個構造的重載:C++11 提出的引用構造(右值引用) eg: string(string&& s )

4 .既然編譯器能自己生成預設的拷貝構造函數,那我們還要自己定義嗎?

答案是 肯定的。

理由:編譯器并不知道我們的類中是怎樣的成員,有沒有多次使用用一個類對象定義拷貝構造函數,假如說我們在類中 并沒有申請(管理)記憶體空間,那麼出類時,析構函數将會正常的銷毀類中的成員(空間資源),釋放記憶體。 但是, 請你想一想,假如你的類中 申請了空間(管理了記憶體空間),而你申請的空間被拷貝構造函數使用 (換句話說,就是假如拷貝構造函數使用了你申請的記憶體空間,并拷貝出了多個類 類型的對象),這會發生什麼?? 這會導緻你申請的空間被同時多個類類型對象共用(換句話說,多個類類型對象指向同一空間(同一對象)),而析構函數會銷毀你的所有成員,導緻同一申請的空間釋放多次,這當然不行了!!!

是以,我們顯式地寫個拷貝構造函數是很有必要的!(目前我能力還不行,但是道理我懂了,加油)

以下代碼為什麼會崩掉?留待以後回來看看

#include"iostream"
#include"string.h"
#include"stdio.h"
#include "windows.h"
using namespace std;
class String
{
public :
		// 拷貝構造函數
		String(const char* str = "Jack")
	{
		_str = (char*)malloc(strlen(str) + 1);
		strcpy(_str, str);
	}
	//析構函數
	~String()
	{
		cout <<"~String()"<< endl;
		//printf("%s","~String()");
		free(_str);
	}
private:
	char * _str;
};
int main(void)
{
	String s1("hello");//調用編譯器預設生成的構造函數
	String s2(s1);
	system("pause");
	return 0;
}
           

2 指派運算符重載

概念:什麼是指派運算符重載?

指派運算符重載就是:編譯器本來不支援該類型的運算,但是使用者想實作,所是以産生這個函數。

運算符重載是不是聽着就很不一樣??

它也是一種函數重載。

函數格式 : 傳回值類型 + operate +運算符(參數清單){函數體}

特征: operate 關鍵字後邊 + 運算符符号

注意: 1 不能自己建立新的運算符,運算符就是運算符,不是個别人定義的

2 參數清單必須至少有一個 枚舉類型或者類類型的對象

3 運算符的語義不允許更改 eg: 外部為 operate+(參數清單){return a-b;}

這樣是錯誤的!

4 若為類的成員的 (重載)函數,參數還有一個隐藏的this指針,即參數數量+1

5 <1> . * <2 > :: <3>s izeof <4>? : <5> . 這5個運算符不能做重載函數 。筆試題常常出現

繼續閱讀