C++ 動態(tài)數(shù)組模版類Vector實例詳解
1.實現(xiàn)機制
內(nèi)部主要通過m_capacity數(shù)組容量成員和m_length數(shù)組有效長度成員來維護一個T* data數(shù)組空間.
內(nèi)部默認分配一定數(shù)量大小的數(shù)組指針,每次append尾部追加的時候,無需再次分配空間,直接賦值標志length長度,假如超過當前空間容量,則再次擴大分配新的內(nèi)存數(shù)組,并將舊數(shù)組拷貝至新數(shù)組及釋放舊數(shù)組.
Vector需要實現(xiàn)的public函數(shù)如下所示:
inline int capacity()
: 獲取容量inline int length() :
獲取有效長度void resize(int asize) :
改變數(shù)組的有效長度void append(const T &t) :
尾部追加一個元素T& operator[] (int i) :
通過[]獲取元素T operator[] (int i) const :
通過[]獲取常量元素void clear() :
清空數(shù)組中的數(shù)據(jù)inline bool isEmpty():
數(shù)組是否有數(shù)據(jù)
resize()函數(shù)實現(xiàn)細節(jié):
- 如果resize長度大于當前容量時 : 則擴大分配新的內(nèi)存數(shù)組,并將舊數(shù)組拷貝至新數(shù)組及釋放舊數(shù)組.
- 如果resize長度小于當前l(fā)ength時 : 則需要將多余的成員進行釋放,調(diào)用析構(gòu)函數(shù)實現(xiàn).
- 如果resize長度大于當前l(fā)ength時 : 則需要調(diào)用默認構(gòu)造函數(shù)來填充內(nèi)部數(shù)組.
2.代碼實現(xiàn)
#ifndef VECTOR_H #define VECTOR_H #include "throw.h" // throw.h里面定義了一個ThrowException拋異常的宏,如下所示: //#include <iostream> //using namespace std; //#define ThrowException(errMsg) {cout<<__FILE__<<" LINE"<<__LINE__<<": "<<errMsg<<endl; (throw errMsg);} template <typename T> class Vector { T* m_data; int m_length; // 有效數(shù)據(jù)的長度 int m_capacity; // 分配容量的長度 // 分配 T* allocate(int size) { T* arr = new T[size]; if(arr == NULL) { ThrowException( "No memory to create DynamicArray object ..."); } return arr; } // 重新分配 void realloc(int capacity) { T* newData = allocate(capacity); for(int i=0; i<m_length; i++) { newData[i] = m_data[i]; } delete[] m_data; m_data = newData; m_capacity = capacity; } // 調(diào)用析構(gòu)函數(shù) void destruct(int from, int end) { while(from++<end) { m_data[from].~T(); } } // 調(diào)用默認構(gòu)造函數(shù) void defaultConstruct(int from, int end) { while(from++<end) { m_data[from] = T(); } } public: Vector(int lenght = 50) { m_length = 0; m_data = allocate(lenght); m_capacity = lenght; } inline int capacity() const { return m_capacity; } // 獲取容量 inline int size() { return m_length; } // 獲取有效長度 inline int length() { return size(); } inline T *data() { return m_data; } inline const T *data() const { return m_data; } inline bool isEmpty() const { return m_length == 0; } void clear() { if(!m_length) return; destruct(0, m_length); m_length = 0; } void resize(int asize) { if(asize == m_length) return; // 重新分配的大小>當前容量時 if(asize > m_capacity) { realloc(asize); } if (asize < m_length) // 分配的大小<當前大小時,則調(diào)用析構(gòu) destruct(asize, m_length); else // 分配的大小>當前大小時,則調(diào)用默認構(gòu)造 defaultConstruct(m_length, asize); m_length = asize; } // 尾部追加一個元素 void append(const T &t) { if(m_length == m_capacity) { realloc(m_capacity+20); // 如果容量滿了,則默認增加20個容量.方便后面append無需再次分配內(nèi)存 } m_data[m_length] = t; m_length++; } T& operator[] (int i) { if((0 <= i) && (i < length())) { return m_data[i]; } else { ThrowException("Parameter i is invalid ..."); } } T operator[] (int i) const { return m_data[i]; } }; #endif // VECTOR_H
3.測試運行
測試如下所示:
class Test { public: int number; Test(int n = 0) { number = n; } }; int main(int argc, char *argv[]) { Vector<Test> arr; for(int i = 0; i < 10; i++) arr.append(Test(i)); cout<<"********* Arr Len:"<<arr.length()<<" capacity:"<<arr.capacity()<<endl; for(int i = 0; i < arr.length(); i++) cout<<"arr []:"<<arr[i].number<<endl; cout<<"*********"<<endl; arr.resize(13); cout<<"********* Arr Len:"<<arr.length()<<" capacity:"<<arr.capacity()<<endl; for(int i = 0; i < arr.length(); i++) cout<<"arr []:"<<arr[i].number<<endl; cout<<"*********"<<endl; arr.resize(5); cout<<"********* Arr Len:"<<arr.length()<<" capacity:"<<arr.capacity()<<endl; for(int i = 0; i < arr.length(); i++) cout<<"arr []:"<<arr[i].number<<endl; cout<<"*********"<<endl; return 0; }
運行如下所示:
可以看到我們resize(13)后,由于 resize長度大于當前arr的length,所以則調(diào)用默認構(gòu)造函數(shù)來填充內(nèi)部數(shù)組.所以arr[10]至arr[12]的number為0。
總結(jié)
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
C++ 中dynamic_cast<>的使用方法小結(jié)
將一個基類對象指針(或引用)cast到繼承類指針,dynamic_cast會根據(jù)基類指針是否真正指向繼承類指針來做相應處理2013-03-03