国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

C++ 模擬實(shí)現(xiàn)vector

這篇具有很好參考價(jià)值的文章主要介紹了C++ 模擬實(shí)現(xiàn)vector。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

目錄

一、定義

二、模擬實(shí)現(xiàn)

1、無參初始化

2、size&capacity

3、reserve

4、push_back

5、迭代器

6、empty

7、pop_back

8、operator[ ]

9、resize

10、insert

迭代器失效問題

11、erase

12、帶參初始化

13、迭代器初始化

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

15、深拷貝

16、賦值運(yùn)算符重載

完整版代碼&測試代碼


一、定義

本次參考SGI版本STL中的vector模擬實(shí)現(xiàn)。

C++ 模擬實(shí)現(xiàn)vector,C++,c++,開發(fā)語言

我們可以看到上述源代碼中,SGI版本vector是借助指針實(shí)現(xiàn)的,元素的處理是通過兩個(gè)指針來實(shí)現(xiàn)的,而不是三個(gè)迭代器。這兩個(gè)指針分別是_start和_finish。

  • _start指針指向vector中的第一個(gè)元素。
  • _finish指針指向vector中最后一個(gè)元素的下一個(gè)位置。

通過_start和_finish指針,可以確定vector中存儲(chǔ)的元素范圍。

C++ 模擬實(shí)現(xiàn)vector,C++,c++,開發(fā)語言?

此外,SGI版本的vector還使用了一個(gè)指針_end_of_storage來表示vector分配的內(nèi)存空間的末尾位置。

這些指針的使用使得SGI版本的vector能夠高效地進(jìn)行元素的插入、刪除和訪問操作。

為了不影響VS中STL庫已有的vector,我們選擇將模擬實(shí)現(xiàn)的vector放在自定義命名空間中。

namespace byte
{
	template<class T>
	class vector
	{
    public:

    private:
    	iterator _start;
    	iterator _finish;
	    iterator _end_of_storage;
    };
}

二、模擬實(shí)現(xiàn)

1、無參初始化

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

2、size&capacity

size_t capacity() const
{
	return _end_of_storage - _start;
}

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

3、reserve

void reserve(size_t n)
{
	if (n > capacity())
	{
		size_t sz = size();
		T* tmp = new T[n];
		if (_start)
		{
			memcpy(tmp, _start, sizeof(T) * size());
			delete[] _start;
		}
		_start = tmp;
		_finish = _start + sz;
		_end_of_storage = _start + n;
	}
}
  1. if (n > capacity()):檢查傳入的n是否大于當(dāng)前vector的容量。如果是,則需要進(jìn)行內(nèi)存重新分配。

  2. size_t sz = size();:保存當(dāng)前vector的大?。ㄔ貍€(gè)數(shù))。

  3. T* tmp = new T[n];:創(chuàng)建一個(gè)新的大小為n的動(dòng)態(tài)數(shù)組tmp,用于存儲(chǔ)重新分配后的元素。

  4. if (_start):檢查_start指針判斷舊空間是否為非空。如果_start指針不為空,說明vector中已經(jīng)有元素存儲(chǔ)在舊的內(nèi)存空間中。

  5. memcpy(tmp, _start, sizeof(T) * size());:使用memcpy函數(shù)將舊的內(nèi)存空間中的元素復(fù)制到新的內(nèi)存空間tmp中。這樣可以保留元素的值。

  6. delete[] _start;:釋放舊的內(nèi)存空間。

  7. _start = tmp;:將_start指針指向新的內(nèi)存空間tmp。

  8. _finish = _start + sz;:更新_finish指針,使其指向新的內(nèi)存空間中的最后一個(gè)元素的下一個(gè)位置。

  9. _end_of_storage = _start + n;:更新_end_of_storage指針,使其指向新的內(nèi)存空間的末尾位置。?

對(duì)上述函數(shù)進(jìn)行改進(jìn):

void reserve(size_t n)
{
	if (n > capacity())
	{
		size_t sz = size();
		T* tmp = new T[n];
		if (_start)
		{
			//memcpy(tmp, _start, sizeof(T)*size());
			for (size_t i = 0; i < sz; ++i)
			{
				tmp[i] = _start[i];
			}
			delete[] _start;
		}
		_start = tmp;
		_finish = _start + sz;
		_end_of_storage = _start + n;
	}
}

第二個(gè)函數(shù)的改進(jìn)在于它使用了元素級(jí)別的復(fù)制(通過賦值操作符)而不是直接內(nèi)存復(fù)制(通過memcpy)。

在第一個(gè)函數(shù)中,memcpy直接復(fù)制了內(nèi)存塊,這對(duì)于平凡的數(shù)據(jù)類型(如整數(shù)、浮點(diǎn)數(shù)、字符等)是沒有問題的,因?yàn)檫@些類型的復(fù)制就是簡單的內(nèi)存復(fù)制。然而,對(duì)于包含自定義復(fù)制行為的類類型,memcpy可能會(huì)導(dǎo)致錯(cuò)誤,因?yàn)樗粫?huì)調(diào)用類的復(fù)制構(gòu)造函數(shù)或賦值操作符。

在第二個(gè)函數(shù)中,通過循環(huán)和賦值操作符進(jìn)行元素級(jí)別的復(fù)制。這樣,如果T是一個(gè)類類型,并且定義了自定義的復(fù)制構(gòu)造函數(shù)或賦值操作符,那么這些函數(shù)將被正確調(diào)用,從而避免了可能的錯(cuò)誤。

因此,第二個(gè)函數(shù)的改進(jìn)在于它更安全,更適合處理包含自定義復(fù)制行為的類類型。

4、push_back

void push_back(const T& x)
{
	if (_finish == _end_of_storage)
	{
		reserve(capacity() == 0 ? 4 : capacity() * 2);
	}
	*_finish = x;
	++_finish;
}
  1. 使用const T& x作為參數(shù)類型可以避免不必要的拷貝操作,因?yàn)閭魅氲膶?shí)參可以直接通過引用訪問,而不需要進(jìn)行拷貝構(gòu)造。這可以提高性能和效率,特別是當(dāng)處理大型對(duì)象時(shí)。

    另外,使用const T& x還可以確保傳入的元素不會(huì)被修改,因?yàn)?code>const關(guān)鍵字表示傳入的引用是只讀的,函數(shù)內(nèi)部不能修改傳入的對(duì)象。

  2. if (_finish == _end_of_storage)?這個(gè)條件判斷用于檢查當(dāng)前vector是否已經(jīng)達(dá)到了內(nèi)存空間的末尾。如果是,則需要進(jìn)行內(nèi)存重新分配。

  3. reserve(capacity() == 0 ? 4 : capacity() * 2)?在需要進(jìn)行內(nèi)存重新分配時(shí),調(diào)用reserve函數(shù)來預(yù)留更多的內(nèi)存空間。這里使用了三目運(yùn)算符,如果當(dāng)前容量為0,則預(yù)留4個(gè)元素的空間,否則將當(dāng)前容量乘以2來預(yù)留更多的空間。

  4. *_finish = x?將傳入的元素x賦值給_finish指針?biāo)赶虻奈恢?,即在vector的末尾插入元素。

  5. ++_finish?將_finish指針向后移動(dòng)一位,指向新插入元素的下一個(gè)位置,以便維護(hù)vector的邊界。

5、迭代器

typedef T* iterator;
typedef const T* const_iterator;

iterator begin()
{
	return _start;
}

iterator end()
{
	return _finish;
}

const_iterator begin() const
{
	return _start;
}

const_iterator end() const
{
	return _finish;
}
  • 首先,通過typedef關(guān)鍵字,定義了兩個(gè)迭代器類型:iteratorconst_iterator。iterator表示可修改元素的迭代器,而const_iterator表示只讀元素的迭代器。
  • 然后,定義了begin()end()函數(shù)的多個(gè)重載版本,用于返回不同類型的迭代器。

6、empty

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

7、pop_back

void pop_back(const T& x)
{
	assert(!empty());
	--_finish;
}

8、operator[ ]

這個(gè)類中有兩個(gè)重載的下標(biāo)運(yùn)算符函數(shù),一個(gè)是非常量版本的?operator[],另一個(gè)是常量版本的?operator[]。這是為了支持對(duì)類對(duì)象的讀寫操作和只讀操作的區(qū)分。

T& operator[](size_t pos)
{
	assert(pos < size());
	return _start[pos];
}

const T& operator[](size_t pos) const
{
	assert(pos < size());
	return _start[pos];
}

9、resize

void resize(size_t n, T val = T())
{
	if (n < size())
	{
		_finish = _start + n;
	}
	else {
		if (n < capacity())
			reserve(n);
		while (_finish != _start + n)
		{
			*_finish = val;
			++_finish;
		}
	}
}

函數(shù)簽名為?void resize(size_t n, T val = T()),接受兩個(gè)參數(shù):n?表示新的大小,val?表示新元素的默認(rèn)值(默認(rèn)為?T(),通過匿名對(duì)象T()調(diào)用類型?T?的默認(rèn)構(gòu)造函數(shù))。

函數(shù)的作用是將容器的大小調(diào)整為?n。如果?n?小于當(dāng)前的大小,則將容器的大小縮小為?n,丟棄多余的元素;如果?n?大于當(dāng)前的大小,則在容器的末尾添加新的元素,直到容器的大小達(dá)到?n

  1. 首先,函數(shù)會(huì)檢查?n?是否小于當(dāng)前的大小。如果是,說明需要縮小容器的大小,將?_finish?指針移動(dòng)到新的位置?_start + n,丟棄多余的元素。
  2. 如果?n?大于等于當(dāng)前的大小,則需要添加新的元素。首先,函數(shù)會(huì)檢查?n?是否大于容器的容量?capacity()。如果?n?大于容量,則調(diào)用?reserve?函數(shù)來增加容器的容量,以確保容器有足夠的空間來存放新的元素。
  3. 然后,使用循環(huán)將新的元素?val?添加到容器的末尾,直到容器的大小達(dá)到?n。循環(huán)中,將?val?賦值給?_finish?指向的位置,然后將?_finish?指針向后移動(dòng)一位。

匿名對(duì)象調(diào)用默認(rèn)構(gòu)造初始化。

    template<class T>
	void f()
	{
		T x = T();
		cout << x << endl;
	}
  • 在?resize?函數(shù)中,T val = T()?是一個(gè)帶有默認(rèn)值的函數(shù)參數(shù)。這里?T()?是對(duì)模板參數(shù)?T?類型的值初始化,對(duì)于內(nèi)置類型,它會(huì)初始化為零(對(duì)于指針類型,初始化為?nullptr)。這和?f<T>()?模板函數(shù)中的?T x = T()?是一樣的。
  • 當(dāng)你調(diào)用?resize?函數(shù)時(shí),如果你沒有提供第二個(gè)參數(shù),那么?val?就會(huì)被初始化為?T?類型的默認(rèn)值。然后,resize?函數(shù)會(huì)使用?val?的值來填充新添加的元素。
  • 例如,如果你有一個(gè)?byte::vector<int>?對(duì)象?v,并調(diào)用?v.resize(10),那么?resize?函數(shù)會(huì)將?v?的大小改變?yōu)?10,并使用?int?類型的默認(rèn)值?0?來填充新添加的元素。這和?f<int>()?函數(shù)打印?int?類型的默認(rèn)值?0?是一樣的。

?內(nèi)置類型的默認(rèn)初始化和直接初始化。

	void test_vector2()
	{
		// 內(nèi)置類型有沒有構(gòu)造函數(shù)
		int i = int();
		int j = int(1);

		f<int>();
		f<int*>();
		f<double>();
	}
  • int i = int();?使用值初始化,將?i?初始化為零。int j = int(1);?使用直接初始化,將?j?初始化為?1。

  • 分別使用?int、int* 和?double?作為模板參數(shù)調(diào)用了?f<T>()?函數(shù)。這將分別打印?int、int* 和?double?類型的默認(rèn)值,即?0、nullptr?和?0。

10、insert

iterator insert(iterator pos, const T& val)
{
	assert(pos >= _start);
	assert(pos <= _finish);

	if (_finish == _end_of_storage)
	{
		size_t len = pos - _start;
		reserve(capacity() == 0 ? 4 : capacity() * 2);

		// 擴(kuò)容后更新pos,解決pos失效的問題
		pos = _start + len;
	}

	iterator end = _finish-1;
	while (end >= pos)
	{
		*(end + 1) = *end;
		--end;
	}

	*pos = val;
	++_finish;

	return pos;
}

函數(shù)接受兩個(gè)參數(shù),第一個(gè)參數(shù)?pos?是一個(gè)迭代器,表示要插入元素的位置,第二個(gè)參數(shù)?val?是要插入的元素的值。

函數(shù)的實(shí)現(xiàn)分為以下幾個(gè)步驟:

  1. 首先,使用?assert?斷言來確保?pos?是一個(gè)有效的位置,即?pos?必須在?_start?和?_finish?之間。

  2. 然后,檢查是否有足夠的空間來插入新的元素。如果?_finish?等于?_end_of_storage,表示當(dāng)前的內(nèi)存已經(jīng)用完,需要重新分配內(nèi)存。這時(shí),會(huì)調(diào)用?reserve?函數(shù)來重新分配內(nèi)存,新的容量是當(dāng)前容量的兩倍,如果當(dāng)前容量為?0,則新的容量為?4。然后,更新?pos?的值,因?yàn)橹匦路峙鋬?nèi)存后,原來的?pos?可能已經(jīng)失效。

  3. 接下來,從?_finish-1?開始,將每個(gè)元素向后移動(dòng)一位,直到?pos?的位置,為插入新的元素騰出空間。

  4. 然后,將?val?的值賦給?*pos,即在?pos?的位置插入新的元素。

  5. 最后,將?_finish?向后移動(dòng)一位,表示?vector?的大小增加了一個(gè)元素。

  6. 函數(shù)返回插入新元素的位置?pos。

迭代器失效問題

  1. 在 `byte::vector` 類的 `insert` 函數(shù)中,如果需要重新分配內(nèi)存(即 `_finish+ + == _end_of_storage`),那么所有指向原來內(nèi)存的迭代器都會(huì)失效。這是因?yàn)?`reserve` 函數(shù)會(huì)申請(qǐng)新的內(nèi)存,復(fù)制原來的元素到新的內(nèi)存,然后釋放原來的內(nèi)存。這個(gè)過程會(huì)導(dǎo)致原來的內(nèi)存地址不再有效,因此所有指向原來內(nèi)存的迭代器都會(huì)失效。
  2. 在這個(gè)函數(shù)中,`pos` 是一個(gè)迭代器,它指向要插入新元素的位置。如果在插入新元素之前需要重新分配內(nèi)存,那么 `pos` 就會(huì)失效。為了解決這個(gè)問題,函數(shù)在重新分配內(nèi)存后,會(huì)根據(jù) `pos` 原來的位置(即 `len = pos - _start`)來更新 `pos` 的值(即 `pos = _start + len`)。這樣,`pos` 就會(huì)指向新內(nèi)存中相同的位置。
  3. 所以,如果你在調(diào)用 `insert` 函數(shù)之后還需要使用原來的迭代器,你需要注意迭代器可能已經(jīng)失效。你可以在插入新元素后,重新獲取迭代器的值。例如,如果你在插入新元素后,想要訪問新元素,這里不能常量pos使用引用傳值,你可以使用 `insert` 函數(shù)的返回值,它返回的是插入新元素的位置。這時(shí)外部插入元素后? (*pos)++; 可以正常運(yùn)行了。

11、erase

我們先看這個(gè)版本的erase:

void erase(iterator pos)
{
	assert(pos >= _start && pos < _finish);
	iterator start = pos + 1;
	while (start != _finish)
	{
		*(start - 1) = *start;
		++start;
	}
	--_finish;
}

?當(dāng)我們運(yùn)行以下代碼程序VS會(huì)報(bào)錯(cuò),linux下g++不會(huì)報(bào)錯(cuò)。

	void test4()
	{
		std::vector<int> v1;
		v1.push_back(1);
		v1.push_back(2);
		v1.push_back(3);
		v1.push_back(4);
		for (auto e : v1)
		{
			cout << e << " ";
		}
		cout << endl;

		auto pos = find(v1.begin(), v1.end(), 2);
		if (pos != v1.end())
		{
			v1.erase(pos);
		}

		(*pos)++;

		for (auto e : v1)
		{
			cout << e << " ";
		}
		cout << endl;
	}
}

VS下:?

C++ 模擬實(shí)現(xiàn)vector,C++,c++,開發(fā)語言

g++下:

C++ 模擬實(shí)現(xiàn)vector,C++,c++,開發(fā)語言

這段代碼中,v1.erase(pos)?會(huì)刪除?vector?中的一個(gè)元素,這會(huì)導(dǎo)致?pos?以及所有在?pos?之后的迭代器失效。然后,代碼試圖通過?(*pos)++?訪問和修改已經(jīng)失效的迭代器?pos,這是未定義行為,可能會(huì)導(dǎo)致程序崩潰或其他錯(cuò)誤。

至于為什么 Visual Studio(VS) 會(huì)報(bào)錯(cuò),而 g++ 不會(huì)報(bào)錯(cuò),這主要是因?yàn)椴煌木幾g器對(duì)未定義行為的處理方式不同。VS 的調(diào)試模式下對(duì)迭代器進(jìn)行了更嚴(yán)格的檢查,當(dāng)你試圖訪問失效的迭代器時(shí),它會(huì)立即報(bào)錯(cuò)。而 g++ 在默認(rèn)設(shè)置下可能不會(huì)進(jìn)行這樣的檢查,所以它可能不會(huì)立即報(bào)錯(cuò),但這并不意味著這段代碼是正確的。

下面第一種情況刪除非末尾元素時(shí),VS的報(bào)錯(cuò)沒有意義,但在第二種情況下,VS的報(bào)錯(cuò)就非常有意義了。?

C++ 模擬實(shí)現(xiàn)vector,C++,c++,開發(fā)語言

為了避免這種問題,你應(yīng)該在刪除元素后,不再使用已經(jīng)失效的迭代器。如果你需要在刪除元素后繼續(xù)訪問?vector,你應(yīng)該在刪除元素后重新獲取迭代器的值。例如,vector::erase?函數(shù)會(huì)返回一個(gè)指向被刪除元素之后的元素的迭代器,你可以使用這個(gè)返回值來更新?pos?。

正確版本:?

iterator erase(iterator pos)
{
	assert(pos >= _start);
	assert(pos < _finish);

	iterator start = pos + 1;
	while (start != _finish)
	{
		*(start - 1) = *start;
		++start;
	}

	--_finish;

	return pos;
}

我們來測試一下刪除偶數(shù):

void test5()
{
	byte::vector<int> v1;
	v1.push_back(1);
	v1.push_back(2);
	v1.push_back(3);
	v1.push_back(4);

	for (auto e : v1)
	{
		cout << e << " ";
	}
	cout << endl;

	//要求刪除所有偶數(shù)
	byte::vector<int>::iterator it = v1.begin();
	while (it != v1.end())
	{
		if (*it % 2 == 0)
		{
			it=v1.erase(it);
		}
		else
		{
			++it;
		}
	}

	for (auto e : v1)
	{
		cout << e << " ";
	}
	cout << endl;
}

?C++ 模擬實(shí)現(xiàn)vector,C++,c++,開發(fā)語言

12、帶參初始化

?一定要對(duì)_start、_finish、_out_of_storage進(jìn)行初始化,不初始化默認(rèn)隨機(jī)值。?

vector(size_t n, const T& value = T())
	: _start(nullptr)
	, _finish(nullptr)
	, _end_of_storage(nullptr)
{
	reserve(n);
	while (n--)
	{
		push_back(value);
	}
}

這個(gè)構(gòu)造函數(shù)創(chuàng)建一個(gè)包含?n?個(gè)元素的?vector,每個(gè)元素都初始化為?value。value?參數(shù)有一個(gè)默認(rèn)值,即?T(),它是?T?類型的默認(rèn)構(gòu)造值。

  • _start(nullptr), _finish(nullptr), _end_of_storage(nullptr): 這一行初始化三個(gè)迭代器,它們分別指向數(shù)組的開始、當(dāng)前最后一個(gè)元素之后的位置,和分配的內(nèi)存末端。初始化為?nullptr?表示開始時(shí)沒有分配任何內(nèi)存。
  • reserve(n): 這個(gè)函數(shù)調(diào)用會(huì)分配足夠容納?n?個(gè)元素的內(nèi)存,但不會(huì)創(chuàng)建任何元素。
  • while (n--) { push_back(value); }: 這個(gè)循環(huán)會(huì)不斷地添加?value?到?vector?中,直到添加了?n?個(gè)元素。push_back?函數(shù)會(huì)在?vector?的末尾添加一個(gè)新元素,并可能會(huì)增加?vector?的容量(如果需要)。

為什么對(duì) T& 前面要加 const ?

  • 匿名對(duì)象聲明周期只在當(dāng)前一行,因?yàn)檫@行之后沒人會(huì)用它了。
  • const引用會(huì)延長匿名對(duì)象的聲明周期到引用對(duì)象域結(jié)束,因?yàn)橐院笥脁x就是用匿名對(duì)象。

C++ 模擬實(shí)現(xiàn)vector,C++,c++,開發(fā)語言

13、迭代器初始化

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

這個(gè)構(gòu)造函數(shù)使用兩個(gè)迭代器?first?和?last,它們分別指向輸入序列的開始和結(jié)束,來初始化?vector。這個(gè)構(gòu)造函數(shù)可以用于從任何可迭代的容器(如另一個(gè)?vector、列表、數(shù)組等)復(fù)制元素。

  • 在這個(gè)構(gòu)造函數(shù)中,沒有顯式地調(diào)用?reserve?來預(yù)分配內(nèi)存。這意味著每次用?push_back?時(shí),如果當(dāng)前容量不足以容納新元素,就會(huì)自動(dòng)進(jìn)行內(nèi)存重新分配。
  • while (first != last) { push_back(*first); ++first; }: 這個(gè)循環(huán)會(huì)遍歷輸入序列的每個(gè)元素,從 first 開始,一直到達(dá) last(但不包括 last),并使用每個(gè)元素的值調(diào)用 push_back,將其添加到 vector 中。

?但是對(duì)于這句代碼編譯之后會(huì)報(bào)錯(cuò):

vector<int> v1(10, 5);

C++ 模擬實(shí)現(xiàn)vector,C++,c++,開發(fā)語言?這是因?yàn)檫@段代碼在vector(InputIterator first, InputIterator last)和vector(size_t n, const T& value = T())同時(shí)存在時(shí),會(huì)優(yōu)先調(diào)用前者,但調(diào)研之后在函數(shù)內(nèi)部first的模板類型為int,而*first為對(duì)int類型解引用,所以這樣報(bào)錯(cuò)了。

我們只要添加一個(gè)int類型重載函數(shù)即可解決。

vector(int n, const T& val = T())
{
	reserve(n);
	for (int i = 0; i < n; ++i)
	{
		push_back(val);
	}
}

?這種情況在不加上上述函數(shù)可以正常使用,調(diào)用vector(size_t n, const T& value = T())。

vector<int> v1(10u, 5);

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

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

15、深拷貝

vector(const vector<T>& v)
{
	_start = new T[v.capacity()];
	//memcoy(_start, v._start, sizeof(T) * v.size());
	for (size_t i = 0; i < size(); i++)
	{
		_start[i] = v._start[i];
	}
	_finish = _start + v.size();
	_end_of_storage = _start + v.capacity();
}

也可以調(diào)用迭代器區(qū)間構(gòu)造tmp,再借助swap交換實(shí)現(xiàn)深拷貝。?文章來源地址http://www.zghlxwxcb.cn/news/detail-756812.html

vector(const vector<T>& v)
{
	vector<T> tmp(v.begin(), v.end());
	swap(tmp);
}

16、賦值運(yùn)算符重載

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

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

完整版代碼&測試代碼

#pragma once
#include<assert.h>
namespace byte
{
	template<class T>
	class vector
	{
	public:
		typedef T* iterator;
		typedef const T* const_iterator;

		iterator begin()
		{
			return _start;
		}

		iterator end()
		{
			return _finish;
		}

		const_iterator begin() const
		{
			return _start;
		}

		const_iterator end() const
		{
			return _finish;
		}

		void resize(size_t n, T val = T())
		{
			if (n < size())
			{
				_finish = _start + n;
			}
			else {
				if (n < capacity())
					reserve(n);
				while (_finish != _start + n)
				{
					*_finish = val;
					++_finish;
				}
			}
		}

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

		vector(size_t n, const T& value = T())
			: _start(nullptr)
			, _finish(nullptr)
			, _end_of_storage(nullptr)
		{
			reserve(n);
			while (n--)
			{
				push_back(value);
			}
		}

		vector(int n, const T& val = T())
		{
			reserve(n);
			for (int i = 0; i < n; ++i)
			{
				push_back(val);
			}
		}

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

		vector(const vector<T>& v)
		{
			_start = new T[v.capacity()];
			//memcoy(_start, v._start, sizeof(T) * v.size());
			for (size_t i = 0; i < size(); i++)
			{
				_start[i] = v._start[i];
			}
			_finish = _start + v.size();
			_end_of_storage = _start + v.capacity();
		}

		~vector()
		{
			delete[] _start;
			_start = _finish = _end_of_storage = nullptr;
		}
		
		void reserve(size_t n)
		{
			if (n > capacity())
			{
				size_t sz = size();
				T* tmp = new T[n];
				if (_start)
				{
					//memcpy(tmp, _start, sizeof(T)*size());
					for (size_t i = 0; i < sz; ++i)
					{
						tmp[i] = _start[i];
					}
					delete[] _start;
				}
				_start = tmp;
				_finish = _start + sz;
				_end_of_storage = _start + n;
			}
		}

		void push_back(const T& x)
		{
			if (_finish == _end_of_storage)
			{
				reserve(capacity() == 0 ? 4 : capacity() * 2);
			}
			*_finish = x;
			++_finish;
		}

		void pop_back(const T& x)
		{
			assert(!empty());
			--_finish;
		}

		void insert(iterator pos, const T& val)
		{
			assert(pos >= _start);
			assert(pos <= _finish);
			
			if (_finish == _end_of_storage)
			{
				size_t len = pos - _start;
				reserve(capacity() == 0 ? 4 : capacity() * 2);
				pos = _start + len;
			}

			iterator end = _finish - 1;
			while (end >= pos)
			{
				*(end + 1) = *end;
				--end;
			}
			*pos = val;
			++_finish;
		}

		iterator erase(iterator pos)
		{
			assert(pos >= _start && pos < _finish);
			iterator start = pos + 1;
			while (start != _finish)
			{
				*(start - 1) = *start;
				++start;
			}
			--_finish;

			return pos;
		}

		size_t capacity() const
		{
			return _end_of_storage - _start;
		}

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

		bool empty()
		{
			return _start == _finish;
		}
		T& operator[](size_t pos)
		{
			assert(pos < size());
			return _start[pos];
		}

		const T& operator[](size_t pos) const
		{
			assert(pos < size());
			return _start[pos];
		}
	private:
		iterator _start;
		iterator _finish;
		iterator _end_of_storage;
	};


	void func(const vector<int>& v)
	{
		for (size_t i = 0; i < v.size(); ++i)
		{
			cout << v[i] << " ";
		}
		cout << endl;

		vector<int>::const_iterator it = v.begin();
		while (it != v.end())
		{
			cout << *it << " ";
			++it;
		}
		cout << endl << endl;
	}

	void test1()
	{
		vector<int> v1;
		v1.push_back(1);
		v1.push_back(2);
		v1.push_back(3);
		for (size_t i = 0; i < v1.size(); i++)
		{
			cout << v1[i] << " ";
		}
		cout << endl;

		vector<int>::iterator it = v1.begin();
		while (it != v1.end())
		{
			cout << *it << " ";
			++it;
		}
		cout << endl;

		for (auto e : v1)
		{
			cout << e << " ";
		}
		cout << endl;
	}

	void test2()
	{
		vector<int> v1;
		v1.push_back(1);
		v1.push_back(2);
		v1.push_back(3);
		v1.push_back(4);
		v1.push_back(5);

		cout << v1.size() << endl;
		cout << v1.capacity() << endl;

		v1.resize(10);

		cout << v1.size() << endl;
		cout << v1.capacity() << endl;

		func(v1);

		v1.resize(3);

		func(v1);
	}

	void test3()
	{
		std::vector<int> v1;
		v1.push_back(1);
		v1.push_back(2);
		v1.push_back(3);
		v1.push_back(4);
		//v1.push_back(5);
		for (auto e : v1)
		{
			cout << e << " ";
		}
		cout << endl;

		/*v1.insert(v1.begin(), 0);
		for (auto e : v1)
		{
		cout << e << " ";
		}
		cout << endl;*/

		auto pos = find(v1.begin(), v1.end(), 3);
		if (pos != v1.end())
		{
			//v1.insert(pos, 30);
			pos = v1.insert(pos, 30);
		}

		for (auto e : v1)
		{
			cout << e << " ";
		}
		cout << endl;

		// insert以后我們認(rèn)為pos失效了,不能再使用
		(*pos)++;

		for (auto e : v1)
		{
			cout << e << " ";
		}
		cout << endl;
	}

	void test4()
	{
		std::vector<int> v1;
		v1.push_back(1);
		v1.push_back(2);
		v1.push_back(3);
		v1.push_back(4);
		for (auto e : v1)
		{
			cout << e << " ";
		}
		cout << endl;

		//auto pos = find(v1.begin(), v1.end(), 2);
		auto pos = find(v1.begin(), v1.end(), 4);
		if (pos != v1.end())
		{
			v1.erase(pos);
		}

		(*pos)++;

		for (auto e : v1)
		{
			cout << e << " ";
		}
		cout << endl;

	}

	void test5()
	{
		byte::vector<int> v1;
		v1.push_back(1);
		v1.push_back(2);
		v1.push_back(3);
		v1.push_back(4);

		for (auto e : v1)
		{
			cout << e << " ";
		}
		cout << endl;

		//要求刪除所有偶數(shù)
		byte::vector<int>::iterator it = v1.begin();
		while (it != v1.end())
		{
			if (*it % 2 == 0)
			{
				it=v1.erase(it);
			}
			else
			{
				++it;
			}
		}

		for (auto e : v1)
		{
			cout << e << " ";
		}
		cout << endl;
	}

	void test6()
	{
		vector<int> v1(10, 5);
		for (auto e : v1)
		{
			cout << e << " ";
		}
		cout << endl;

		vector<int> v2(v1.begin() + 1, v1.end() - 1);
		for (auto e : v2)
		{
			cout << e << " ";
		}
		cout << endl;

		std::string s1("hello");
		vector<int> v3(s1.begin(), s1.end());
		for (auto e : v3)
		{
			cout << e << " ";
		}
		cout << endl;

		int a[] = { 100, 10, 2, 20, 30 };
		vector<int> v4(a, a + 3);
		for (auto e : v4)
		{
			cout << e << " ";
		}
		cout << endl;

		v1.insert(v1.begin(), 10);
		for (auto e : v1)
		{
			cout << e << " ";
		}
		cout << endl;
	}
}

到了這里,關(guān)于C++ 模擬實(shí)現(xiàn)vector的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 【C++】vector容器的模擬實(shí)現(xiàn)

    目錄 一,框架設(shè)計(jì) 二,構(gòu)造函數(shù) 三,析構(gòu)函數(shù) 四,賦值運(yùn)算符 五,容器接口的實(shí)現(xiàn) 1,迭代器實(shí)現(xiàn) 2,“ []?”運(yùn)算符的實(shí)現(xiàn) 3,swap交換和resize重設(shè)大小 4,insert插入和erase刪除 介紹: ? ? ? ? 本文,我們重點(diǎn)實(shí)現(xiàn)vector容器的用法,這里要注意的是vector容器可以接納任意類

    2024年02月02日
    瀏覽(20)
  • C++——vector類及其模擬實(shí)現(xiàn)

    C++——vector類及其模擬實(shí)現(xiàn)

    前言:前邊我們進(jìn)行的string類的方法及其模擬實(shí)現(xiàn)的講解。這篇文章將繼續(xù)進(jìn)行C++的另一個(gè)常用類——vector。 vector和string一樣, 隸屬于C++中STL標(biāo)準(zhǔn)模板庫中的一個(gè)自定義數(shù)據(jù)類型 ,實(shí)際上就是 線性表 。 兩者之間有著很多相似,甚至相同的方法 。 但是它們也有著很大的不

    2024年04月13日
    瀏覽(20)
  • 【C++】vector模擬實(shí)現(xiàn)及其應(yīng)用

    【C++】vector模擬實(shí)現(xiàn)及其應(yīng)用

    vector是表示可變大小數(shù)組的序列容器。 就像數(shù)組一樣,vector也采用的連續(xù)存儲(chǔ)空間來存儲(chǔ)元素。也就是意味著可以采用下標(biāo)對(duì)vector的元素進(jìn)行訪問,和數(shù)組一樣高效。但是又不像數(shù)組,它的大小是可以動(dòng)態(tài)改變的,而且它的大小會(huì)被容器自動(dòng)處理。 本質(zhì)講,vector使用動(dòng)態(tài)分

    2023年04月25日
    瀏覽(18)
  • C++:vector使用以及模擬實(shí)現(xiàn)

    C++:vector使用以及模擬實(shí)現(xiàn)

    和我們?cè)瓉碇v的string不同, vector并不是類,是一個(gè)類模板,加類型實(shí)例化以后才是類。 vector是表示 可變大小數(shù)組 的序列容器。 像數(shù)組一樣 ,vector也采用的連續(xù)存儲(chǔ)空間來存儲(chǔ)元素,但是容量可以動(dòng)態(tài)改變。 和其它容器相比,vector訪問元素、尾插、尾刪較高效,但不在尾部

    2024年02月11日
    瀏覽(19)
  • C++中的vector類模擬實(shí)現(xiàn)

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

    目錄 vector模擬實(shí)現(xiàn) vector類設(shè)計(jì) vector類構(gòu)造函數(shù) vector類根據(jù)個(gè)數(shù)構(gòu)造函數(shù) vector類根據(jù)迭代器區(qū)間構(gòu)造函數(shù) vector類拷貝構(gòu)造函數(shù) vector類賦值運(yùn)算符重載函數(shù) vector類析構(gòu)函數(shù) vector類獲取有效數(shù)據(jù)個(gè)數(shù)函數(shù) vector類獲取容量大小函數(shù) vector類begin()函數(shù) vector類end()函數(shù) vector類reser

    2024年04月13日
    瀏覽(25)
  • 【C++ STL】vector模擬實(shí)現(xiàn)
  • C++ STL vector 模擬實(shí)現(xiàn)

    C++ STL vector 模擬實(shí)現(xiàn)

    ?1主頁:我的代碼愛吃辣 ??2知識(shí)講解:C++之STL ??3創(chuàng)作者:我的代碼愛吃辣 ??4開發(fā)環(huán)境:Visual Studio 2022 ??5前言:上次我們已經(jīng)數(shù)字會(huì)用了vector,這次我們對(duì)其底層更深一步挖掘,其中重點(diǎn)是,Vector中一些深淺拷貝問題。 目錄 一.Vector模擬實(shí)現(xiàn)的整體框架 二. Vector的構(gòu)

    2024年02月13日
    瀏覽(33)
  • 【C++】vector的使用及其模擬實(shí)現(xiàn)

    【C++】vector的使用及其模擬實(shí)現(xiàn)

    vector 是表示 可變大小數(shù)組的序列容器。 就像數(shù)組一樣,vector也采用的連續(xù)存儲(chǔ)空間來存儲(chǔ)元素。也就是意味著可以 采用下標(biāo)對(duì)vector的元素進(jìn)行訪問 ,和數(shù)組一樣高效。但是又不像數(shù)組, 它的大小是可以動(dòng)態(tài)改變的,而且它的大小會(huì)被容器自動(dòng)處理。 本質(zhì)講,vector使用動(dòng)態(tài)

    2024年02月02日
    瀏覽(30)
  • vector類模擬實(shí)現(xiàn)(c++)(學(xué)習(xí)筆記)

    vector類模擬實(shí)現(xiàn)(c++)(學(xué)習(xí)筆記)

    基本框架: vector的大致形狀如下:黃色代表每天滿的地方。 使用初始化列表實(shí)現(xiàn)一個(gè)簡單的無參構(gòu)造函數(shù)。 記住要帶[]即可。 因?yàn)閜ush_back涉及到擴(kuò)容函數(shù),需要實(shí)現(xiàn)reserve()。 如下示例: 問題1:_finish賦值出錯(cuò),出bug了,是因?yàn)閟ize()函數(shù),調(diào)用了空指針,導(dǎo)致報(bào)錯(cuò)。 改正:

    2024年02月05日
    瀏覽(17)
  • C++ [STL之vector模擬實(shí)現(xiàn)]

    C++ [STL之vector模擬實(shí)現(xiàn)]

    本文已收錄至《C++語言》專欄! 作者:ARMCSKGT vector是STL容器容器之一,其底層實(shí)現(xiàn)類似于數(shù)據(jù)結(jié)構(gòu)順序表,相當(dāng)于string來說得益于泛型模板的加持使得vector可以變?yōu)槿魏晤愋?,且是可以?dòng)態(tài)擴(kuò)容,堪稱大號(hào)數(shù)組!在vector的實(shí)現(xiàn)中,有許多值得我們學(xué)習(xí)的細(xì)節(jié),接下來將為大家

    2024年02月11日
    瀏覽(22)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包