真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

【C++】STL---vector的模擬實(shí)現(xiàn)(超級詳細(xì),萬字詳解)-創(chuàng)新互聯(lián)

文章目錄
  • 前言
  • vector的成員屬性
  • 構(gòu)造函數(shù)
  • size函數(shù)
  • cacpcity函數(shù)
  • begin和end函數(shù)
  • reserve函數(shù)
  • insert函數(shù)
  • push_back函數(shù)
  • []操作符重載
  • 析構(gòu)函數(shù)
  • 拷貝構(gòu)造函數(shù)
  • 賦值操作符重載
  • erase函數(shù)
  • pop_back
  • 反向迭代器
    • 反向迭代器模板
    • 反向迭代器的構(gòu)造函數(shù)
    • ++運(yùn)算符重載
    • - -運(yùn)算符重載
    • *引用操作符重載
    • !=操作符重載
    • ==操作符重載
    • rbegin函數(shù)
    • rend函數(shù)
    • ->重載
  • 總結(jié)

專注于為中小企業(yè)提供網(wǎng)站設(shè)計、成都網(wǎng)站建設(shè)服務(wù),電腦端+手機(jī)端+微信端的三站合一,更高效的管理,為中小企業(yè)阜陽免費(fèi)做網(wǎng)站提供優(yōu)質(zhì)的服務(wù)。我們立足成都,凝聚了一批互聯(lián)網(wǎng)行業(yè)人才,有力地推動了近1000家企業(yè)的穩(wěn)健成長,幫助中小企業(yè)通過網(wǎng)站建設(shè)實(shí)現(xiàn)規(guī)模擴(kuò)充和轉(zhuǎn)變。
前言

vector 是一個順序容器,簡單來說就是一個可以擴(kuò)容的數(shù)組。它的數(shù)據(jù)在內(nèi)存中是連續(xù)存儲的。這也就意味著它支持隨機(jī)訪問(下標(biāo)訪問),而這篇文章將會帶著大家模擬實(shí)現(xiàn)一個vector的容器。


vector的成員屬性

vector是一個順序容器,那么我們需要給它分配空間。那么我們可以用三個迭代器來指向,_start迭代器指向第一個位置,_finish指向有效數(shù)據(jù)的下一個位置,而_endofstorage指向開辟空間大小的最后一個位置。

代碼:

templateclass vector
{public:
	//普通迭代器
	typedef T* iterator;
	//const迭代器
	typedef const T* const_iterator;
private:
	iterator _start;
	iterator _finish;
	iterator _endofstorage;
	
};

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

接下來我們就要給vector初始化,這里用2種初始化方式,一種是普通初始化。而一種是迭代器區(qū)間初始化。
普通初始化:什么也不干,迭代器初始化成空指針。
迭代器區(qū)間初始化:把迭代器區(qū)間的所有值一一加到當(dāng)前的vector對象種。

普通初始化代碼:

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

迭代器區(qū)間初始化:

//迭代器區(qū)間初始化
	templatevector(InputIterator first, InputIterator last)
		:_start(nullptr)
		,_finish(nullptr)
		,_endofstorage(nullptr)
	{while (first != last)
		{	//把迭代器數(shù)據(jù)依次插入當(dāng)前對象
			push_back(*first);//尾部插入數(shù)據(jù)的函數(shù),在下面實(shí)現(xiàn)
			++first;
		}
	}

size函數(shù)

size函數(shù)返回vector的長度,也就是已經(jīng)存放的數(shù)據(jù)個數(shù),我們直接返回_finish - _start的值即可。

size_t size()
	{return _finish - _start;
	}

如果是const對象,我們也要返回一個長度

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

cacpcity函數(shù)

cacpcity函數(shù)返回vector的容量,也就是能存放的數(shù)據(jù)的大個數(shù),我們直接返回_endofstorage - _start的值即可。

size_t cacpcity()
	{return _endofstorage - _start;
	}

如果是const對象,我們也要返回

size_t cacpcity()const
	{return _endofstorage - _start;
	}

begin和end函數(shù)

begin 獲取 迭代器開始位置,end 獲取迭代器結(jié)束位置。

直接返回_start 和 _finish

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

當(dāng)我們的容器是const的時候,我們需要返回const迭代器。所以還需要對begin和end函數(shù)進(jìn)行函數(shù)重載。

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

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

reserve函數(shù)

reserve函數(shù)是用來改變?nèi)萘康?,但是對于縮容我們不做處理,reserve只做增容處理。

我們可以分以下步驟:

  1. 開辟一塊指定大小的空間(只增容)。
  2. 把原_start空間的數(shù)據(jù)拷貝到新空間。
  3. 更新_finish。
  4. 釋放原來的_start。
  5. 更新_start 和 _endofstorage

代碼:

void reserve(size_t n)
	{//n比當(dāng)前容量大
			if (cacpcity()< n)
			{		//開辟n個空間
				T* tmp = new T[n];
				//拷貝
				for (int i = 0; i< size(); i++)
				{*(tmp + i) = *(_start + i);
				}
				//更新_finish
				_finish = tmp + size();
				//銷毀舊空間
				delete[] _start;
				//更新
				_start = tmp;
				_endofstorage = _start + n;
			}
	}

insert函數(shù)

insert函數(shù)是在容器指定位置插入一個數(shù)據(jù),而實(shí)現(xiàn)insert后我們可以復(fù)用insert實(shí)現(xiàn)push_back尾插函數(shù)。
而這個指定位置,我們用迭代器來表示。插入完后,我們返回插入數(shù)據(jù)的迭代器位置,方便迭代。

	指定位置插入
		iterator insert(iterator pos, const T& val)
		{	//pos必須在 _start  - _finish之間
			assert(pos >= _start && pos<= _finish);
			//判斷空間是否足夠
			if (_finish == _endofstorage)
			{		size_t len = pos - _start;
				//空間不夠,增容,是0增容4,不是0增容2倍
				reserve(cacpcity() == 0 ? 4 : 2 * cacpcity());
				pos = _start + len;
			}
			//把pos - finish 的位置都往后移動
			iterator end = _finish;
			while (end >pos)
			{		*(end) = *(end - 1);
				--end;
			}
			*pos = val;
			++_finish;
			//返回pos迭代器
			return pos;
		}
push_back函數(shù)

push_back是一個尾插函數(shù),而我們前面實(shí)現(xiàn)過insert,所以可以直接復(fù)用。

void push_back(const T& val)
		{	//復(fù)用insert
			insert(end(), val);
		}
[]操作符重載

我們要支持下標(biāo)訪問,可以重載[]操作符,給定一個下標(biāo),返回_start+下標(biāo)的解引用的引用即可。

T& operator[](const T& val)
		{	return *(_start + val);;
		}

如果是const對象,那么我們不允許修改[]的值。

const T& operator[](const T& val)const
		{	return *(_start + val);;
		}
析構(gòu)函數(shù)

直接釋放_start的空間即可。

~vector()
		{	delete[] _start;
			_start = _finish = _endofstorage = nullptr;
		}
拷貝構(gòu)造函數(shù)

我們可以用 被拷貝對象的迭代區(qū)間實(shí)例化一個對象,再把當(dāng)前對象與這個對象進(jìn)行交換。
然后出了函數(shù),實(shí)例化的對象會被自動析構(gòu)。

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

		vector(const vector& v)
		{	vectortmp(v.begin(), v.end());
			//交換
			swap(tmp);
		}
賦值操作符重載

直接用拷貝構(gòu)造構(gòu)造一個,然后和當(dāng)前對象交換。

vector& operator=(const vectorv)
		{	vector v2(v);
			swap(v2);
			return *this;
		}
erase函數(shù)

eraser函數(shù)是在指定位置刪除,我們依舊通過迭代器的方式刪除。刪除后,返回原來下標(biāo)的迭代器。

代碼:

iterator erase(iterator pos)
		{	//pos必須在start - finish區(qū)間,且 size不能為空
			assert(size() >0);
			assert(pos >= _start && pos< _finish);
			int len = pos - _start;
			//從pos的下一個位置開始,往前覆蓋
			iterator begin = pos + 1;
			while (begin != _finish)
			{		*(begin - 1) = *begin;
				++begin;
			}
			_finish--;

			return pos;
		}
pop_back

pop_back是一個尾刪函數(shù),也就是刪除最后一個數(shù)據(jù),我們可以復(fù)用erase

void pop_back()
		{	erase(end() - 1);
		}

end是指向最后一個數(shù)據(jù)的下一個位置,所以 -1 就是最后一個數(shù)據(jù)。

反向迭代器

反向迭代器我們需要再有一個類來封裝它,目的是為了讓它具有復(fù)用性。不僅讓它可以在 vector中使用,在list里也可以復(fù)用 。

反向迭代器模板

我們可以用模板來接收,目的是為了讓它既能生成普通反向迭代器,也可以生成帶有const的反向迭代器。iterator是傳過來的普通迭代器,Ref是返回解引用后的值,Ptr是返回指針。

templateclass _reverse_iterator
{typedef _reverse_iteratorself;
public:	
private:
	iterator reverse_iterator;
};
反向迭代器的構(gòu)造函數(shù)

反向迭代器其實(shí)就是正向迭代器封裝,只是++操作變–,–操作變++

_reverse_iterator(iterator it)
		:_it(it)
	{}
++運(yùn)算符重載

反向迭代器的++是普通迭代器的- -

//前置++
	self& operator++()
	{--_it;
		return *this;
	}
	//后置++
	self operator++(int)
	{self tmp(*this);
		--_it;
		return tmp;
	}
- -運(yùn)算符重載

反向迭代器的- - 是正向迭代器的++

//前置--
	self& operator--()
	{++_it;
		return *this;
	}
	//后置--
	self operator--(int)
	{self tmp(*this);
		++_it;
		return tmp;
	}
*引用操作符重載

根據(jù)官方的stl,解引用返回的其實(shí)是它反向迭代器的前一個位置。
因?yàn)槠鹗嘉恢檬窃谧詈笠粋€數(shù)據(jù)的下一個位置。
在這里插入圖片描述
所以返回它的前一個位置即可

Ref operator*()
	{iterator tmp = (*this)._it;
		return *(--tmp);
	}

然后我們在主類里面加上模板。

typedef _reverse_iteratorreverse_iterator;
typedef _reverse_iteratorconst_reverse_iterator;

在這里插入圖片描述

!=操作符重載

比較地址相不相等,直接返回結(jié)果即可。

bool operator!=(const self& it)
	{return _it != it._it;
	}

	bool operator!=(const self& it)const
	{return _it != it._it;
	}
==操作符重載

一樣,直接返回結(jié)果即可。

bool operator==(const self& it)
	{return _it == it._it;
	}

	bool operator==(const self& it)const
	{return _it == it._it;
	}
rbegin函數(shù)

rbegin函數(shù)返回最后一個數(shù)據(jù)的下一個位置,也就是_finish,那我們就用_finish實(shí)例化一個反向迭代器。

reverse_iterator rbegin()
		{	return reverse_iterator(_finish);
		}

對于const容器,我們返回const的反向迭代器

const_reverse_iterator rbegin()const
		{	return const_reverse_iterator(_finish);
		}
rend函數(shù)

rend函數(shù)就是第一個元素,我們用_start實(shí)例化反向迭代器然后返回。

reverse_iterator rend()
		{	return reverse_iterator(_start);
		}

const 容器返回const的反向迭代器

const_reverse_iterator rend()const
		{	return const_reverse_iterator(_start);
		}
->重載

如果我們vector存的是一個對象類型,我們還需要支持->訪問。所以重載->操作符。

Ptr operator->()
	{		return &operator*();;
	}

我們->也要返回前一個地址,而*操作符返回的是解引用后的值,我們對這個值取地址即可。


全部代碼:
vector.h全部代碼:

#pragma once
#include
#include#include"reverse_iterator.h"
using namespace std;
namespace wyl
{templateclass vector
	{public:
		//普通迭代器
		typedef T* iterator;
		//const迭代器
		typedef const T* const_iterator;
		//反向迭代器
		typedef _reverse_iteratorreverse_iterator;
		typedef _reverse_iteratorconst_reverse_iterator;

		vector()
			:_start(nullptr)
			, _finish(nullptr)
			, _endofstorage(nullptr)
		{}
		//迭代器區(qū)間初始化
		templatevector(InputIterator first, InputIterator last)
			:_start(nullptr)
			, _finish(nullptr)
			, _endofstorage(nullptr)
		{	while (first != last)
			{		//把迭代器數(shù)據(jù)依次插入當(dāng)前對象
				push_back(*first);
				++first;
			}
		}

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

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

		vector(const vector& v)
		{	vectortmp(v.begin(), v.end());
			//交換
			swap(tmp);
		}

		T& operator[](const T& val)
		{	return *(_start + val);
		}

		vector& operator=(const vectorv)
		{	vector v2(v);
			swap(v2);
			return *this;
		}

		const T& operator[](const T& val)const
		{	return *(_start + val);;
		}

		size_t size()
		{	return _finish - _start;
		}

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


		size_t cacpcity()
		{	return _endofstorage - _start;
		}
		size_t cacpcity()const
		{	return _endofstorage - _start;
		}

		void reserve(size_t n)
		{	//n比當(dāng)前容量大
			if (cacpcity()< n)
			{		//開辟n個空間
				T* tmp = new T[n];
				//拷貝
				for (int i = 0; i< size(); i++)
				{*(tmp + i) = *(_start + i);
				}
				//更新_finish
				_finish = tmp + size();
				//銷毀舊空間
				delete[] _start;
				//更新
				_start = tmp;
				_endofstorage = _start + n;
			}
		}

		指定位置插入
		iterator insert(iterator pos, const T& val)
		{	//pos必須在 _start  - _finish之間
			assert(pos >= _start && pos<= _finish);
			//判斷空間是否足夠
			if (_finish == _endofstorage)
			{		size_t len = pos - _start;
				//空間不夠,增容,是0增容4,不是0增容2倍
				reserve(cacpcity() == 0 ? 4 : 2 * cacpcity());
				pos = _start + len;
			}
			//把pos - finish 的位置都往后移動
			iterator end = _finish;
			while (end >pos)
			{		*(end) = *(end - 1);
				--end;
			}
			*pos = val;
			++_finish;
			//返回pos迭代器
			return pos;
		}

		iterator erase(iterator pos)
		{	//pos必須在start - finish區(qū)間,且 size不能為空
			assert(size() >0);
			assert(pos >= _start && pos< _finish);
			int len = pos - _start;
			//從pos的下一個位置開始,往前覆蓋
			iterator begin = pos + 1;
			while (begin != _finish)
			{		*(begin - 1) = *begin;
				++begin;
			}
			_finish--;

			return pos;
		}

		void pop_back()
		{	erase(end() - 1);
		}

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

		const_iterator begin()const
		{	return _start;
		}
		const_iterator end()const
		{	return _finish;
		}
		//反向迭代器
		reverse_iterator rbegin()
		{	return reverse_iterator(_finish);
		}

		const_reverse_iterator rbegin()const
		{	return const_reverse_iterator(_finish);
		}

		reverse_iterator rend()
		{	return reverse_iterator(_start);
		}

		const_reverse_iterator rend()const
		{	return const_reverse_iterator(_start);
		}


		void push_back(const T& val)
		{	//復(fù)用insert
			insert(end(), val);
		}

	private:
		iterator _start;
		iterator _finish;
		iterator _endofstorage;

	};


	void a(const vector& v)
	{for (int i = 0; i< v.size(); i++)
		{	//v[i] = 10;
			cout<< v[i]<< " ";
		}
	}
	void test1()
	{vectorv;
		v.push_back(1);
		cout<< v.size()<< ","<< v.cacpcity()<< endl;
		v.push_back(2);
		cout<< v.size()<< ","<< v.cacpcity()<< endl;
		v.push_back(3);
		cout<< v.size()<< ","<< v.cacpcity()<< endl;
		v.push_back(4);
		v.push_back(5);
		cout<< v.size()<< ","<< v.cacpcity()<< endl;
		
		vector::iterator it = v.begin();
		//while (it != v.end())
		//{//	
		//	cout<< *it<< " ";
		//	++it;
		//}
		for (int i = 0; i< v.size(); i++)
		{	v[i] = 10;
			cout<< v[i]<< " ";
		}
		a(v);

	}

	void test2()
	{vectorv;
		v.push_back(1);
		v.push_back(2);
		v.push_back(3);
		v.push_back(4);
		v.push_back(5);
		//v.erase(v.begin());
		//v.erase(v.end()-1);


		vectorv2 = v;
		vector::reverse_iterator rit = v2.rbegin();
		while (rit != v2.rend())
		{	
			cout<< *rit<< " ";
			++rit;
		}
	}
	struct Date
	{int _year;
		int _month;
		int _day;
		Date(int year = 1,int month = 1,int day = 1)
			:_year(year)
			,_month(month)
			,_day(day)
		{}
	};

	void b(const vector& v)
	{vector::const_reverse_iterator rit = v.rbegin();
		while (rit != v.rend())
		{	cout<< rit->_year<< " "<< rit->_month<< " "<< rit->_day<< endl;
			++rit;
		}
	}

	void test3()
	{vectorv;
		v.push_back(Date(2022, 1, 1));
		v.push_back(Date(2022, 2, 1));
		v.push_back(Date(2022, 3, 1));
		b(v);

	}
}

反向迭代器封裝的類的全部代碼
reverse_iterator.h

#pragma once

templateclass _reverse_iterator
{typedef _reverse_iteratorself;
public:	
	_reverse_iterator(iterator it)
		:_it(it)
	{}
	//前置++
	self& operator++()
	{--_it;
		return *this;
	}
	//后置++
	self operator++(int)
	{self tmp(*this);
		--_it;
		return tmp;
	}

	//前置--
	self& operator--()
	{++_it;
		return *this;
	}
	//后置--
	self operator--(int)
	{self tmp(*this);
		++_it;
		return tmp;
	}

	Ref operator*()
	{iterator tmp = (*this)._it;
		return *(--tmp);
	}

	Ptr operator->()
	{return &operator*();
	}

	bool operator!=(const self& it)
	{return _it != it._it;
	}

	bool operator!=(const self& it)const
	{return _it != it._it;
	}

	bool operator==(const self& it)
	{return _it == it._it;
	}

	bool operator==(const self& it)const
	{return _it == it._it;
	}


private:
	iterator _it;
};

主main函數(shù)文件代碼
test.cpp

#include"vector.h"

void vectorTest()
{//wyl::test1();
	wyl::test3();

}

int main()
{vectorTest();
}
總結(jié)

代碼是跟著博客邊寫,邊測,沒問題才寫上博客的。而后續(xù)還會為大家更新更多關(guān)于stl的知識,以及一些容器的模擬實(shí)現(xiàn)。而反向迭代器具有復(fù)用性,也就是這次實(shí)現(xiàn)了,下次模擬實(shí)現(xiàn)其他容器時可以直接帶進(jìn)去用。實(shí)際中vector的使用頻率也很高,手動實(shí)現(xiàn)一次vector對學(xué)習(xí)stl的幫助也非常大。后續(xù)會持續(xù)為大家更新關(guān)于C/C++,數(shù)據(jù)結(jié)構(gòu)以及l(fā)inux操作系統(tǒng)等知識,如果覺得講的還可以,可以三連關(guān)注一下。如果哪里有寫的不對的地方,也歡迎大家指出。

你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級服務(wù)器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧


分享標(biāo)題:【C++】STL---vector的模擬實(shí)現(xiàn)(超級詳細(xì),萬字詳解)-創(chuàng)新互聯(lián)
文章來源:http://weahome.cn/article/dgoejj.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部