欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++中vector的模擬實(shí)現(xiàn)實(shí)例詳解

 更新時(shí)間:2021年11月12日 16:36:04   作者:小倪同學(xué) -_-  
vector是表示可變大小數(shù)組的序列容器,它也采用連續(xù)存儲(chǔ)空間來(lái)存儲(chǔ)元素,因此可以采用下標(biāo)對(duì)vector的元素進(jìn)行訪問(wèn),這篇文章主要給大家介紹了關(guān)于C++中vector模擬實(shí)現(xiàn)的相關(guān)資料,需要的朋友可以參考下

vector接口總覽

namespace nzb
{
	//模擬實(shí)現(xiàn)vector
	template<class T>
	class vector
	{
	public:
		typedef T* iterator;
		typedef const T* const_iterator;

		//默認(rèn)成員函數(shù)
		vector();                                           //構(gòu)造函數(shù)
		vector(size_t n, const T& val);                     //構(gòu)造函數(shù)
		template<class InputIterator>
		vector(InputIterator first, InputIterator last);    //構(gòu)造函數(shù)
		vector(const vector<T>& v);                         //拷貝構(gòu)造函數(shù)
		vector<T>& operator=(const vector<T>& v);           //賦值重載
		~vector();                                          //析構(gòu)函數(shù)

		//迭代器相關(guān)函數(shù)
		iterator begin();
		iterator end();
		const_iterator begin()const;
		const_iterator end()const;

		//容量相關(guān)函數(shù)
		size_t size()const;
		size_t capacity()const;
		void reserve(size_t n);
		void resize(size_t n, const T& val = T());
		bool empty()const;

		//修改容器相關(guān)函數(shù)
		void push_back(const T& x);
		void pop_back();
		void insert(iterator pos, const T& x);
		iterator erase(iterator pos);
		void swap(vector<T>& v);

		//訪問(wèn)容器相關(guān)函數(shù)
		T& operator[](size_t i);
		const T& operator[](size_t i)const;

	private:
		iterator _start;        //指向容器的頭
		iterator _finish;       //指向有效數(shù)據(jù)的尾
		iterator _endofstorage; //指向容器的尾
	};
}

默認(rèn)成員函數(shù)

構(gòu)造函數(shù)

1、無(wú)參構(gòu)造,將所有成員變量初始化為空指針即可

vector()
	:_start(nullptr)
	, _finish(nullptr)
	, _endofstorage(nullptr)
{}

2、構(gòu)造一個(gè)含有n個(gè)值為val的vector容器。

先將容器容量擴(kuò)大到n,再尾插val

vector(size_t n, const T& val)
	:_start(nullptr)
	, _finish(nullptr)
	, _endofstorage(nullptr)
{
	reserve(n); //擴(kuò)容
	for (size_t i = 0; i < n; i++) //尾插
	{
		push_back(val);
	}
}

3、利用迭代器區(qū)間進(jìn)行構(gòu)造

因?yàn)榈鲄^(qū)間可以是其他迭代器區(qū)間,所以我們要重新定義一塊模板,再將迭代器中的數(shù)據(jù)尾插

template <class InputIterator>
vector(InputIterator first, InputIterator last)
	:_start(nullptr)
	, _finish(nullptr)
	, _endofstorage(nullptr)
{
	while (first != last)
	{
			push_back(*first);
			first++;
	}
}

拷貝構(gòu)造

傳統(tǒng)寫法

先將容器容量擴(kuò)大到n,再尾插原vector類中的數(shù)據(jù)(這里擴(kuò)容和尾插調(diào)整了容器尾指針和數(shù)據(jù)尾指針,我們不必再次調(diào)整)

vector(const vector<T>& v)
	:_start(nullptr)
	, _finish(nullptr)
	, _endofstorage(nullptr)
{
	reserve(v.capacity());
	for (const auto& e : v)
	{
		push_back(e);
	}
}

現(xiàn)代寫法

利用迭代器構(gòu)造一份vector類,再交換該類和拷貝構(gòu)造的類

		vector(const vector<T>& v)
			:_start(nullptr)
			, _finish(nullptr)
			, _endofstorage(nullptr)
		{
			vector<T> tmp(v.begin(), v.end());
			swap(tmp);
		}

賦值重載

傳統(tǒng)寫法

先初始化原來(lái)vector類的空間,再將數(shù)據(jù)拷貝過(guò)來(lái)

vector<T>& operator=(const vector<T>& v)
{
	if (this != &v)
	{
		delete[] _start;
		_start = _finish = _endofstorage = nullptr;

		reserve(v.capacity());
		for (const auto& e : v)
		{
			push_back(e);
		}
	}	
	return *this;
}

現(xiàn)代寫法

現(xiàn)代寫法極為巧妙,利用傳值的特性(出了函數(shù)立即銷毀)傳入vector類,再交換該類和拷貝構(gòu)造的類達(dá)到賦值的效果

vector<T>& operator=(vector<T> v)
{
	swap(v);
	return *this;
}

析構(gòu)函數(shù)

釋放開辟存儲(chǔ)數(shù)據(jù)的空間,再將容器的各個(gè)成員變量置為空

~vector()
{
	delete[] _start;
	_start = _finish = _endofstorage = nullptr;
}

迭代器相關(guān)函數(shù)

vector當(dāng)中的迭代器實(shí)際上就是容器當(dāng)中所存儲(chǔ)數(shù)據(jù)類型的指針。

typedef T* iterator;
typedef const T* const_iterator;

begin和end

vector當(dāng)中的begin函數(shù)返回容器的首地址,end函數(shù)返回容器當(dāng)中有效數(shù)據(jù)的下一個(gè)數(shù)據(jù)的地址。

iterator begin()
{
	return _start;
}
iterator end()
{
	return _finish;
}

我們還需寫一份const版本,const版本只能讀不能寫,防止vector中數(shù)據(jù)被修改

const_iterator begin() const
{
	return _start;
}
const_iterator end() const
{
	return _finish;
}

容量相關(guān)函數(shù)

size和capacity

size表示vector容器中已存儲(chǔ)有效數(shù)據(jù)個(gè)數(shù)而capacity表示vector容器的最大容量,那如何得出該組數(shù)據(jù)呢?

我們知道vector成員函數(shù)_start,_finish,_endofstorage是指針,而指針減指針得到兩個(gè)指針間的數(shù)據(jù)個(gè)數(shù),我們可以用_finish-_start得到size,用_endofstorage-_start得到capacity

size_t size() const
{
	return _finish - _start;
}
size_t capacity() const
{
	return _endofstorage - _start;
}

reserve

當(dāng)n大于當(dāng)前的capacity時(shí),將capacity擴(kuò)大到n或大于n。

當(dāng)n小于當(dāng)前capacity時(shí)什么也不做。

void reserve(size_t n)
{
	if (n > capacity()) 
	{
		size_t sz = size(); // 記錄原容器中數(shù)據(jù)個(gè)數(shù)
		T* tmp = new T[n]; // 開辟一塊容量為n的空間
		if (_start) //判空
		{
			for (size_t i = 0; i < sz; i++) // 拷貝數(shù)據(jù)
			{
				tmp[i] = _start[i];
			}
			delete[] _start; // 釋放原容器中的數(shù)據(jù)
		}
		_start = tmp; // 調(diào)整指針
		_finish = _start + sz; 
		_endofstorage = _start + n; 
	}
}

注意:這里拷貝數(shù)據(jù)不能用memcpy。當(dāng)我們拷貝的是一些簡(jiǎn)單的常量時(shí)是沒(méi)有問(wèn)題的,但是當(dāng)我們拷貝的是另一個(gè)類,如string類時(shí),拷貝的string還是指向原來(lái)string類指向的空間。當(dāng)原來(lái)string被釋放時(shí),原string類指向的空間也被釋放,此時(shí)拷貝的string類指向的是一塊已被釋放的空間,程序結(jié)束時(shí)它將再次被釋放,釋放一塊已被釋放的空間程序報(bào)錯(cuò)。

resize

當(dāng)n大于當(dāng)前的size時(shí),將size擴(kuò)大到n,擴(kuò)大的數(shù)據(jù)為val,若val未給出,則默認(rèn)為容器所存儲(chǔ)類型的默認(rèn)構(gòu)造函數(shù)所構(gòu)造出來(lái)的值。

當(dāng)n小于當(dāng)前的size時(shí),將size縮小到n。

void resize(size_t n, const T& val = T())
{
	if (n <= size())// 當(dāng)n小于當(dāng)前的size時(shí)
	{
		_finish = n + _start;// 將size縮小到n
	}
	else // 當(dāng)n大于當(dāng)前的size時(shí)
	{
		if (n > capacity())// 當(dāng)n大于容量時(shí),擴(kuò)容
		{
			reserve(n);
		}

		while (_finish < _start + n)// 給size到容器結(jié)尾賦值
		{
			*_finish = val;
			_finish++;
		}
	}
}

這里用了匿名對(duì)象T()來(lái)作為缺省參數(shù)

empty

通過(guò)比較_start和_finish指針來(lái)判斷容器是否為空

bool empty()const
{
	return _start == _finish;
}

修改容器相關(guān)函數(shù)

push_back

先判斷容器是否已滿,如果滿了先擴(kuò)容再尾插,如果沒(méi)滿,直接尾插

void push_back(const T& x)
{
	if (_finish == _endofstorage)// 判斷是否需要擴(kuò)容
	{
		size_t newcapacity = capacity() == 0 ? 4 : capacity() * 2;
		reserve(newcapacity);
	}
	// 尾插數(shù)據(jù)
	*_finish = x;
	_finish++;
}

pop_back

先判空處理,再–_finish

void pop_back()
{
	assert(!empty());// 判空
	--_finish;
}

insert

功能:利用迭代器再指定位置插入數(shù)據(jù)。

實(shí)現(xiàn)方式:插入前判斷是否需要擴(kuò)容,再將指定位置后的數(shù)據(jù)往后挪動(dòng)一位,把數(shù)據(jù)插入指定位置。

iterator insert(iterator pos, const T& x)
{
	assert(pos >= _start&&pos <= _finish);// 判斷傳入數(shù)據(jù)的合法性
	if (_finish == _endofstorage)// 擴(kuò)容
	{
		size_t len = pos - _start;// 記錄pos的位置
		size_t newcapacity = capacity() == 0 ? 4 : capacity() * 2;
		reserve(newcapacity);
		pos = _start + len;
	}
	iterator end = _finish - 1;
	while (end >= pos)// 挪動(dòng)數(shù)據(jù)
	{
		*(end + 1) = *end;
		--end;
	}
	*pos = x;// 插入數(shù)據(jù)
	_finish++;
	return pos;
}

注意:擴(kuò)容時(shí)要記錄pos和_start的相對(duì)位置,避免擴(kuò)容后迭代器失效問(wèn)題

erase

功能:刪除指定位置數(shù)據(jù)。

實(shí)現(xiàn)方式:先判斷傳入數(shù)據(jù)的合法性,在將pos位置后的數(shù)據(jù)全部往前挪動(dòng)一位,覆蓋掉原pos位置的數(shù)據(jù)

iterator erase(iterator pos)
{
	assert(pos >= _start&&pos < _finish);// 判斷傳入數(shù)據(jù)的合法性
	iterator it = pos + 1;// 利用迭代器記錄pos的后一位
	while (it != _finish)// 將pos后的數(shù)據(jù)往前挪動(dòng)一位
	{
		*(it - 1) = *it;
		it++;
	}
	_finish--;

	return pos;
}

swap

功能:交換兩個(gè)vector中的數(shù)據(jù)

實(shí)現(xiàn)方式:利用庫(kù)函數(shù)中的swap進(jìn)行交換

void swap(vector<T>& v)
{
	std::swap(_start, v._start);
	std::swap(_finish, v._finish);
	std::swap(_endofstorage, v._endofstorage);
}

訪問(wèn)容器相關(guān)函數(shù)

operator[ ]

為了方便訪問(wèn)數(shù)據(jù)vector中也加入了“下標(biāo)+[ ]”操作

T& operator[](size_t i)// 可讀可寫
{
	assert(i < size());
	return _start[i];
}

const T& operator[](size_t i) const// 只能讀
{
	assert(i<size());
	return _start[i];
}

總結(jié)

到此這篇關(guān)于C++中vector的模擬實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)C++ vector模擬實(shí)現(xiàn)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 深入理解鏈表的各類操作詳解

    深入理解鏈表的各類操作詳解

    本篇文章是對(duì)鏈表的各類操作進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • C++類與對(duì)象的重點(diǎn)知識(shí)點(diǎn)詳細(xì)分析

    C++類與對(duì)象的重點(diǎn)知識(shí)點(diǎn)詳細(xì)分析

    類和對(duì)象是兩種以計(jì)算機(jī)為載體的計(jì)算機(jī)語(yǔ)言的合稱。對(duì)象是對(duì)客觀事物的抽象,類是對(duì)對(duì)象的抽象。類是一種抽象的數(shù)據(jù)類型;變量就是可以變化的量,存儲(chǔ)在內(nèi)存中—個(gè)可以擁有在某個(gè)范圍內(nèi)的可變存儲(chǔ)區(qū)域
    2023-02-02
  • C++實(shí)現(xiàn)LeetCode(104.二叉樹的最大深度)

    C++實(shí)現(xiàn)LeetCode(104.二叉樹的最大深度)

    這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(104.二叉樹的最大深度),本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-07-07
  • 深入分析C語(yǔ)言分解質(zhì)因數(shù)的實(shí)現(xiàn)方法

    深入分析C語(yǔ)言分解質(zhì)因數(shù)的實(shí)現(xiàn)方法

    這篇文章主要介紹了深入分析C語(yǔ)言分解質(zhì)因數(shù)的實(shí)現(xiàn)方法,作者結(jié)合了ACM題目作為相關(guān)拓展,需要的朋友可以參考下
    2015-08-08
  • 深入理解QT多線程編程

    深入理解QT多線程編程

    本文主要介紹了QT多線程編程的深入理解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-06-06
  • 利用C語(yǔ)言實(shí)現(xiàn)掃雷游戲

    利用C語(yǔ)言實(shí)現(xiàn)掃雷游戲

    這篇文章主要為大家詳細(xì)介紹了利用C語(yǔ)言實(shí)現(xiàn)掃雷游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • C++中Qt的安裝與配置步驟詳解

    C++中Qt的安裝與配置步驟詳解

    Qt是一種C++編程框架,用于構(gòu)建圖形用戶界面(GUI)應(yīng)用程序和嵌入式系統(tǒng),無(wú)論是初學(xué)者還是經(jīng)驗(yàn)豐富的開發(fā)者,Qt都為構(gòu)建高質(zhì)量、可維護(hù)的應(yīng)用程序提供了豐富的工具和支持,本文主要給大家介紹了C++中Qt的安裝與配置步驟,需要的朋友可以參考下
    2023-12-12
  • C語(yǔ)言中長(zhǎng)度為0的數(shù)組詳解

    C語(yǔ)言中長(zhǎng)度為0的數(shù)組詳解

    這篇文章主要給大家介紹了關(guān)于C語(yǔ)言中長(zhǎng)度為0的數(shù)組,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-10-10
  • Qt實(shí)現(xiàn)棋盤游戲

    Qt實(shí)現(xiàn)棋盤游戲

    這篇文章主要為大家詳細(xì)介紹了Qt實(shí)現(xiàn)棋盤游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • VisualStudio2019配置OpenCV4.5.0的方法示例

    VisualStudio2019配置OpenCV4.5.0的方法示例

    這篇文章主要介紹了VisualStudio2019配置OpenCV4.5.0的方法示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03

最新評(píng)論