個人可以做視頻網(wǎng)站嗎企業(yè)查詢寶
一、C++內(nèi)存管理
? ? ? ? 在C語言中我們曾學(xué)習(xí)過動態(tài)內(nèi)存管理的相關(guān)知識,通過malloc、calloc、realloc和free等對堆上的空間進行申請和釋放。在C++中我們同樣會面臨類似的需求,因此C++對動態(tài)開辟內(nèi)存的方式進行了一些調(diào)整,我們可以使用new和delete操作符來對堆空間進行空間管理。
????????①首先要明確的是new和delete的使用方法。new操作符后跟隨需要開辟空間的類型,然后會返回一個指針。delete后跟隨動態(tài)開辟出的指針并對其指向的空間進行釋放。
????????②new可以在其后使用方括號來一次性申請多個同類型的空間,此時就是使用了操作符new[]。在釋放空間的時候也應(yīng)該對應(yīng)匹配地使用delete[]來正確合理釋放空間。
? ? ? ? ③new操作符在開辟空間時可以進行初始化,對于內(nèi)置類型初始化值在類型后使用圓括號表示。對于一次申請了多個同類型空間,初始化使用大括號。如果沒有大括號則認為沒有初始化,得到的空間均為隨機值;如果初始化了但不完全,那么沒有初始化的部分會默認初始化為0。
? ? ? ? ④當(dāng)new的delete的類型為自定義對象時,則會調(diào)用其對應(yīng)的構(gòu)造函數(shù)和析構(gòu)函數(shù)。
class A
{
public:A(int a, int b):_a(a),_b(b){cout << "A(int, int)" << endl;}~A(){cout << "~A(int, int)" << endl;}
private:int _a;int _b;
};
int main()
{//對于內(nèi)置類型:int* p1 = new int; //動態(tài)申請int類型空間int* p2 = new int(2); //使用圓括號動態(tài)申請的空間進行初始化int* p3 = new int[4]; //使用方括號標識申請的數(shù)量int* p4 = new int[6] {1, 2, 3}; //使用大括號進行初始化,不完全初始化下(new時使用了大括號),未初始化的空間默認為0delete p1; //釋放空間使用deletedelete p2;delete[] p3; //釋放new[]的空間,使用delete[]delete[] p4;//對于自定義類型A* pa1 = new A(1, 2); //new自定義類型時會自動調(diào)用構(gòu)造函數(shù)進行初始化//A* pa1 = new A; //error,因為new自定義類型時會調(diào)用構(gòu)造函數(shù),A沒有默認構(gòu)造函數(shù),所以會報錯A* pa2 = new A[4]{ {1,2},{2,3},{3,4},{4,5} }; //new多個自定義類型變量并初始化delete pa1; //delete自定義類型時會自動調(diào)用析構(gòu)函數(shù)進行銷毀delete[] pa2; //delete[]釋放new[]的空間//new的使用不需要進行檢查,當(dāng)出錯時malloc會持續(xù)進行開辟空指針,new則會拋異常return 0;
}
? ? ? ? ⑤使用new申請空間時不需要進行檢查(在C語言中我們會對malloc返回的指針進行非空檢查),因為當(dāng)開辟空間出現(xiàn)問題時,new會直接拋異常而不是返回空指針。
? ? ? ? ⑥對于new和delete,這二者是提供給我們所使用的動態(tài)內(nèi)存申請和釋放的操作符,而實際上還有操作系統(tǒng)提供的operator new和operator delete兩個全局函數(shù)。new在使用時調(diào)用了operator new來幫助自己進行空間申請,同樣的delete調(diào)用了operator delete來進行釋放空間。而operator new和operator delete兩個函數(shù)的開辟空間和釋放空間實際上又是通過調(diào)用malloc和free來實現(xiàn)的。
? ? ? ? 這樣一層層的調(diào)用看似復(fù)雜,實際上是這樣一層層的包含才有了我們可以方便使用,功能完善的new。
? ? ? ? 同理,對于new[]和delete[]而言,調(diào)用了operator new[]和operator delete[]兩個函數(shù)。然后由operator new[]和operator delete[]調(diào)用了operator new和operator delete。再然后調(diào)用了malloc和free來實現(xiàn)。
二、模板
? ? ? ? 在以往寫代碼的時候,常常會遇到針對不同類型的功能相同的函數(shù),這些函數(shù)代碼相同區(qū)別只在于類型不同,但卻因此要寫好幾份來滿足我們的需求。C++中引入模板的概念來很好的解決這個問題。
1. 函數(shù)模板
? ? ? ? 通過提供一個函數(shù)模板,在后續(xù)使用函數(shù)的時候,只需要標明所需要的類型即可由編譯器根據(jù)我們所寫的模板生成對應(yīng)的函數(shù)。
? ? ? ? 在定義函數(shù)模板時,需要使用template關(guān)鍵字,然后使用尖括號和關(guān)鍵字typename或class來指定模板參數(shù),該參數(shù)在使用中會由編譯器自動推演為合適的類型。具體的使用,也就是函數(shù)模板實例化有兩種方式,由編譯器自動推演或者直接顯式實例化。
? ? ? ? 當(dāng)存在函數(shù)的同時又存在模板的情況下,若參數(shù)匹配則會優(yōu)先選擇函數(shù),否則會使用模板。如果采取顯式實例化的方式則會強制使用模板。
//函數(shù)模板
template<typename T>
void Swap(T& a, T& b)
{T tmp = a;a = b;b = tmp;
}
//模板和函數(shù)可以同時存在,調(diào)用時優(yōu)先選擇函數(shù)
//如果函數(shù)不夠匹配,則使用模板
void Swap(int& a, int& b)
{int tmp = a;a = b;b = tmp;
}
template<class T1,class T2> //模板參數(shù)可以多個,以逗號分隔,關(guān)鍵字也可以是class
void func()
{}
int main()
{int a1 = 10, a2 = 20;cout << a1 << ' ' << a2 << endl;Swap(a1, a2); //函數(shù)模板實例化,int類型 //使用函數(shù)cout << a1 << ' ' << a2 << endl;double d1 = 1.2, d2 = 3.7;cout << d1 << ' ' << d2 << endl;Swap(d1, d2); //函數(shù)模板實例化,double類型 //使用模板cout << d1 << ' ' << d2 << endl;Swap<double>(d1, d2); //函數(shù)模板顯式實例化 //顯示實例化強制使用模板cout << d1 << ' ' << d2 << endl;return 0;
}
2. 類模板
? ? ? ? 類模板和函數(shù)模板非常相似,在之后我們會頻繁接觸到類模板。需要注意的是類模板中的成員函數(shù)聲明與定義分離時需要在定義處附加模板參數(shù)列表,并且二者必須在同一文件中。
//類模板
template<class T>
class Stack
{
public:void Push(T x){}
private:T* _a;int _size;int _capacity;
};
int main()
{Stack<int> st1; //類模板實例化Stack<double> st2;return 0;
}