C++ 動(dòng)態(tài)數(shù)組模版類Vector實(shí)例詳解
1.實(shí)現(xiàn)機(jī)制
內(nèi)部主要通過m_capacity數(shù)組容量成員和m_length數(shù)組有效長度成員來維護(hù)一個(gè)T* data數(shù)組空間.
內(nèi)部默認(rèn)分配一定數(shù)量大小的數(shù)組指針,每次append尾部追加的時(shí)候,無需再次分配空間,直接賦值標(biāo)志length長度,假如超過當(dāng)前空間容量,則再次擴(kuò)大分配新的內(nèi)存數(shù)組,并將舊數(shù)組拷貝至新數(shù)組及釋放舊數(shù)組.
Vector需要實(shí)現(xiàn)的public函數(shù)如下所示:
inline int capacity(): 獲取容量inline int length() :獲取有效長度void resize(int asize) :改變數(shù)組的有效長度void append(const T &t) :尾部追加一個(gè)元素T& operator[] (int i) :通過[]獲取元素T operator[] (int i) const :通過[]獲取常量元素void clear() :清空數(shù)組中的數(shù)據(jù)inline bool isEmpty():數(shù)組是否有數(shù)據(jù)
resize()函數(shù)實(shí)現(xiàn)細(xì)節(jié):
- 如果resize長度大于當(dāng)前容量時(shí) : 則擴(kuò)大分配新的內(nèi)存數(shù)組,并將舊數(shù)組拷貝至新數(shù)組及釋放舊數(shù)組.
- 如果resize長度小于當(dāng)前l(fā)ength時(shí) : 則需要將多余的成員進(jìn)行釋放,調(diào)用析構(gòu)函數(shù)實(shí)現(xiàn).
- 如果resize長度大于當(dāng)前l(fā)ength時(shí) : 則需要調(diào)用默認(rèn)構(gòu)造函數(shù)來填充內(nèi)部數(shù)組.
2.代碼實(shí)現(xiàn)
#ifndef VECTOR_H
#define VECTOR_H
#include "throw.h"
// throw.h里面定義了一個(gè)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)用默認(rèn)構(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;
// 重新分配的大小>當(dāng)前容量時(shí)
if(asize > m_capacity) {
realloc(asize);
}
if (asize < m_length) // 分配的大小<當(dāng)前大小時(shí),則調(diào)用析構(gòu)
destruct(asize, m_length);
else // 分配的大小>當(dāng)前大小時(shí),則調(diào)用默認(rèn)構(gòu)造
defaultConstruct(m_length, asize);
m_length = asize;
}
// 尾部追加一個(gè)元素
void append(const T &t)
{
if(m_length == m_capacity) {
realloc(m_capacity+20); // 如果容量滿了,則默認(rèn)增加20個(gè)容量.方便后面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_H3.測(cè)試運(yùn)行
測(cè)試如下所示:
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;
}運(yùn)行如下所示:

可以看到我們resize(13)后,由于 resize長度大于當(dāng)前arr的length,所以則調(diào)用默認(rèn)構(gòu)造函數(shù)來填充內(nèi)部數(shù)組.所以arr[10]至arr[12]的number為0。
總結(jié)
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
C語言詳解鏈?zhǔn)疥?duì)列與循環(huán)隊(duì)列的實(shí)現(xiàn)
隊(duì)列(Queue)與棧一樣,是一種線性存儲(chǔ)結(jié)構(gòu),它具有如下特點(diǎn):隊(duì)列中的數(shù)據(jù)元素遵循“先進(jìn)先出”(First In First Out)的原則,簡稱FIFO結(jié)構(gòu)。在隊(duì)尾添加元素,在隊(duì)頭刪除元素,本篇來講解鏈?zhǔn)疥?duì)列與循環(huán)隊(duì)列的實(shí)現(xiàn)2022-04-04
Linux下Select多路復(fù)用實(shí)現(xiàn)簡易聊天室示例
大家好,本篇文章主要講的是Linux下Select多路復(fù)用實(shí)現(xiàn)簡易聊天室示例,感興趣的同學(xué)趕快來看一看吧,對(duì)你有幫助的話記得收藏一下,方便下次瀏覽2021-12-12
C++?重載運(yùn)算符在HotSpot?VM中的應(yīng)用小結(jié)
C++支持運(yùn)算符重載,對(duì)于Java開發(fā)者來說,這個(gè)可能比較陌生一些,因?yàn)镴ava不支持運(yùn)算符重載,下面介紹一下HotSpot?VM中的運(yùn)算符重載,感興趣的朋友跟隨小編一起看看吧2023-09-09
C++實(shí)踐分?jǐn)?shù)類中運(yùn)算符重載的方法參考
今天小編就為大家分享一篇關(guān)于C++實(shí)踐分?jǐn)?shù)類中運(yùn)算符重載的方法參考,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2019-02-02
C++11 模板參數(shù)的“右值引用”是轉(zhuǎn)發(fā)引用嗎
這篇文章主要介紹了C++11 模板參數(shù)的“右值引用”是轉(zhuǎn)發(fā)引用嗎,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-05-05
C++使用QTcreator創(chuàng)建動(dòng)態(tài)庫流程
在工程中,經(jīng)常會(huì)根據(jù)不同的場景需求將類封裝成庫文件,本文主要介紹了C++使用QTcreator創(chuàng)建動(dòng)態(tài)庫流程,具有一定的參考價(jià)值,感興趣的可以了解一下2024-06-06

