<四>MyVector中加入迭代器功能

来源:https://www.cnblogs.com/erichome/archive/2022/11/22/16915769.html
-Advertisement-
Play Games

我們之前有<C++模板編程模塊>中的第<四>節 理解空間配置器allocator優化STL中的Vector 我將在此基礎上加入迭代器功能代碼 Iterator 為什麼可以遍歷所有的容器的方式都一樣? auto it =continer.beign(); for( ;it!=continer.end( ...


我們之前有<C++模板編程模塊>中的第<四>節 理解空間配置器allocator優化STL中的Vector
我將在此基礎上加入迭代器功能代碼


Iterator 為什麼可以遍歷所有的容器的方式都一樣?
auto it =continer.beign();
for( ;it!=continer.end();++it){
    cout<<*it<<endl;
}

//我們在自己的容器里的 Iterator  de ++ , * 由自己來實現,所有對外部使用者來看都是統一的.
//泛型演算法能夠給所有的容器都使用,也是基於容器對外提供了統一的遍歷介面, 其參數接受的都是容器的迭代器


#include <iostream>
using namespace std;


class person {
public:
	//構造函數
	person(int _age=1,char * _pname=nullptr):
	age(_age)
	{
		if (_pname == nullptr) {
			pname = new char[1];
			pname[0] = '\0';
		}
		else {
			int size = strlen(_pname);
			pname = new char[size + 1];
			strcpy(pname, _pname);
		}
		cout << "創建student對象,地址=" << this << endl;
	}
	//拷貝構造函數
	person(const person & _person) {
		this->age = _person.age;
		int size = strlen(_person.pname);
		pname = new char[size + 1];
		strcpy(this->pname, _person.pname);

	}

	//賦值函數
	person & operator=(const person & _person) {
		if (this == &_person) { return *this; }
		delete[]pname;
		pname = nullptr;
		this->age = _person.age;
		int size = strlen(_person.pname);
		pname = new char[size + 1];
		strcpy(this->pname, _person.pname);
		return *this;
	}
	~person() {
		cout << "析構 person =" <<pname << " "<<age << endl;
		delete[]pname;
		pname = nullptr;		
	}

	
private:
	int age;
	char * pname;
	friend ostream & operator<<(ostream & out, const person & _value);
};

ostream & operator<<(ostream & out, const person & _value) {
	cout << _value.pname<<" == "<< _value.age << " "  << endl;
	return out;
}


template <typename T>
class Allocate4 {

public:
	
	//分配記憶體空間,不創建對象
	T * allocator(int size=4) {
		return (T *)malloc(sizeof(T)*size);
	}
	
	//在指定的記憶體空間地址,構建 T對象
	void constract(T * pAddress, const T & _val) {
		new (pAddress) T(_val);
	}

	//釋放指定位置的記憶體空間
	void delAllocator(T * pAddress) {
		if (pAddress != nullptr) {
			free(pAddress);
			pAddress = nullptr;
		}
	}

	//析構指定記憶體位置
	void destory(T * pAddress) {
		pAddress->~T();//調用析構函數
	}

};


template<typename T,typename Allocate= Allocate4<T>>
//類模板
class MyVector4 {

public:

	MyVector4<T,Allocate>(int size = 4 , const Allocate _rallocator = Allocate4<T>)
	: _allocator(_rallocator)
	{
		pfirst = _allocator.allocator(size);
		last = pfirst;
		pend = pfirst + size;
		cout << "MyVector開闢記憶體地址=" << pfirst<<endl;
	}

	MyVector4<T, Allocate>(const MyVector4<T, Allocate> & _vector)
	{
		//1:根據原vector的空間大小申請新的記憶體空間
		pfirst = _allocator.allocator(_vector.size());
		last   = pfirst;
		pend   = pfirst + size;

		//2:將原vector空間中的有效對象賦值到新的vector中
		T * _pFlag = _vector.pfirst;
		while (_pFlag != _vector.last) {
			_allocator.constract(last, *_pFlag);
			_pFlag++;
			last++;
		}
	}

	MyVector4<T, Allocate> & operator=(const MyVector4<T, Allocate> & _vector)
	{
		if (this == &_vector) {
			return *this;
		}

		//1:析構現有vector中的有效對象
		T * _pFlag = pfirst;
		while (_pFlag !=last) {
			_allocator.destory(_pFlag);
			_pFlag++;
		}

		//2:釋放現有的vector申請的堆記憶體空間
		_allocator.delAllocator(pfirst);
		pfirst = nullptr;
		pend = nullptr;
		last = nullptr;

		//3:根據_vector的記憶體空間大小,申請新的堆記憶體空間
		pfirst = _allocator.allocator(_vector.size());
		last = pfirst;
		pend = pfirst + _vector.size();
		
		//4:將_vector中有效的對象複製到現在新的堆空間中	
		T * _pFlag = _vector.pfirst;
		while (_pFlag != _vector.last) {
			_allocator.constract(last, *_pFlag);
			_pFlag++;
			last++;
		}
		
	}

	void pushBack(const T & _val)  {
		if (Full()) {
			Expend();
		}
		_allocator.constract(last, _val);	
		cout << "pushBack 原對象 地址=" << &_val  <<"放在記憶體位置 "<<last<< endl;
		this->last++;
	}

	void popBack()  {
		if (Empty()) { return ; }
		_allocator.destory(this->last-1);
		this->last--;
	}

	//記憶體空間擴展
	void Expend() {
		int newSize = 2*this->size();
		
		//1:申請新的記憶體空間
		T * tep_pfirst = _allocator.allocator(newSize);
		T * tep_last = tep_pfirst;
		T * tep_pend = tep_pfirst + newSize;

		//2:原當前vector中原有效的對象複製到新的堆空間上
		T * _pFlag = pfirst;
		while (_pFlag != last) {
			_allocator.constract(tep_last, *_pFlag);
			_pFlag++;
			tep_last++;
		}

		//3:析構原有對象
		_pFlag = pfirst;
		while (_pFlag != last) {
			_allocator.destory(_pFlag);
			_pFlag++;
		}

		//4:釋放原有的vector申請的堆記憶體空間
		_allocator.delAllocator(pfirst);
		pfirst = nullptr;
		pend = nullptr;
		last = nullptr;

		//5:指針重新指向
		pfirst = tep_pfirst;
		last   = tep_last;
		pend   = tep_pend;

		cout << "MyVector空間2倍擴展,新的地址=" << pfirst << endl;
	}

	bool Empty() const {
		return this->pfirst == this->last;
	}
	
	bool Full() const {
		return this->pend == this->last;
	}
	int size() {
		return this->pend - this->pfirst;
	}

	void showVectorInfo() {
		T * tep = pfirst;
		while (tep < last)
		{
			cout << "列印Vector中有效對象地址=" << tep << endl;
			tep++;
		}
	}

	//定義屬於自己的迭代器
	class Iterator {

	public:

		Iterator( T * _pAddress=nullptr):pAddress(_pAddress) {
		}

		const T & operator*() const {
			return *pAddress;
		}

		T & operator*() {
			return *pAddress;
		}
		//前置++
		void operator++() {
			this->pAddress++;
		}

		bool operator!=(const Iterator & src) const {
			return this->pAddress != src.pAddress;
		}

	private:
		T * pAddress;
	};

	Iterator begin() const {
		return Iterator(this->pfirst);
	}

	Iterator end() const {
		return Iterator(this->last);
	}

private:
	T * pfirst;//指向首元素地址
	T * pend;  // 指向容器最後位置的下一個地址
	T * last;  //指向最後一個有效元素的下一個位置
	Allocate _allocator;
};



void testV4() {

	MyVector4<person, Allocate4<person>> v5(4,Allocate4<person>());

	person p1(10,"zs1");
	v5.pushBack(p1);

	person p2(20, "zs2");
	v5.pushBack(p2);

	person p3(30, "zs3");
	v5.pushBack(p3);

	person p4(40, "zs4");
	v5.pushBack(p4);

	v5.showVectorInfo();

	cout << "-------" << endl;
	person p5(50, "zs5");
	v5.pushBack(p5);

	v5.showVectorInfo();


	v5.popBack();

	MyVector4<person, Allocate4<person>>::Iterator  it_begin = v5.begin();
	MyVector4<person, Allocate4<person>>::Iterator  it_end   = v5.end();

	cout << "---iterator begin----" << endl;
	
	for (; it_begin != it_end; ++it_begin) {
		cout << *it_begin << endl;
	}

	cout << "---iterator end----" << endl;

}


int main() {

	testV4();
	system("pause");
	return 0;

}//pendl


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Android網路請求(3) 網路請求框架OkHttp 本節我們來講解OkHtpp網路請求框架 什麼是網路請求框架 在我的理解中,網路請求框架是為了方便我們更加便捷規範的進行網路請求所建的類,我們通過調用該類中的方法可以快速地進行網路請求,切幫我們封裝好了一些數據的處理方法,方便我們用更少的代碼去做 ...
  • Android網路請求(2) 在android網路開發中,除get請求外常見的還有post、put、delete這三種,接下來我們將詳細講解這三種請求及參數 GET請求 我們使用過get請求了,對於我們的日常生活中get請求毫無疑問是最常用的請求方式,大部分的瀏覽器搜索都是通過get請求,如在百度上 ...
  • 最近需要接手別人c#那邊組的一個項目新增頁面,但他們的是React的框架,作為一名後端,沒接觸過,一臉懵逼。。。。。。 說哈我的處理思路: 一、先用相應的程式打開該項目的源碼。如:react用vscode打開 二、先找到了頁面,查看頁面結構 這是我後面加的頁面,可以看出來,less類似css樣式 j ...
  • Express 快速創建 Web 伺服器 express 的基本使用 先安裝express包 npm i [email protected] 1.導入 express const express = require('express'); 2.創建 web 伺服器 const app = express( ...
  • 最近用 antd pro 開發了一些 web 小工具。 antd pro 不僅僅是升級版的 antd 組件,更重要的是提供了全套的前端解決方案,包括前端工程的編譯打包,路由配置,數據管理,樣式和資源的引用,和後端的交互方式。 甚至對於網站的國際化也有支持。 本篇是近期使用antd pro 時,用到的 ...
  • 大家好,EluxJS是一套基於“微模塊”和“模型驅動”的跨平臺、跨框架『同構方案』,歡迎瞭解... 可怕的巨石怪 工作中最可怕的是什麼?是遇到業務複雜且亂作一團的巨石應用。改一發而動全身,無法漸進式重構,也沒人敢對歷史包袱進行優化,欠下的代碼債只能像滾雪球一樣越積越多,終於到某天玩不下去,大佬選擇了 ...
  • 傳統大企業更喜歡私有化部署、個性化交付的傳統模式,因為他們需要更強的管控和更高的安全性。 然而,中小企業付費能力有限,需求往往也更加標準化,所以更喜歡價格更低的、訂購更簡單的SaaS產品。 為了滿足不同客戶的需求,多租戶的底層架構設計是至關重要的。 ...
  • 3. Drools入門案例 全套代碼及資料全部完整提供,點此處下載 本小節通過一個Drools入門案例來讓大家初步瞭解Drools的使用方式、對Drools有一個整體概念。 3.1 業務場景說明 業務場景:消費者在圖書商城購買圖書,下單後需要在支付頁面顯示訂單優惠後的價格。具體優惠規則如下: | 規 ...
一周排行
    -Advertisement-
    Play Games
  • Timer是什麼 Timer 是一種用於創建定期粒度行為的機制。 與標準的 .NET System.Threading.Timer 類相似,Orleans 的 Timer 允許在一段時間後執行特定的操作,或者在特定的時間間隔內重覆執行操作。 它在分散式系統中具有重要作用,特別是在處理需要周期性執行的 ...
  • 前言 相信很多做WPF開發的小伙伴都遇到過表格類的需求,雖然現有的Grid控制項也能實現,但是使用起來的體驗感並不好,比如要實現一個Excel中的表格效果,估計你能想到的第一個方法就是套Border控制項,用這種方法你需要控制每個Border的邊框,並且在一堆Bordr中找到Grid.Row,Grid. ...
  • .NET C#程式啟動閃退,目錄導致的問題 這是第2次踩這個坑了,很小的編程細節,容易忽略,所以寫個博客,分享給大家。 1.第一次坑:是windows 系統把程式運行成服務,找不到配置文件,原因是以服務運行它的工作目錄是在C:\Windows\System32 2.本次坑:WPF桌面程式通過註冊表設 ...
  • 在分散式系統中,數據的持久化是至關重要的一環。 Orleans 7 引入了強大的持久化功能,使得在分散式環境下管理數據變得更加輕鬆和可靠。 本文將介紹什麼是 Orleans 7 的持久化,如何設置它以及相應的代碼示例。 什麼是 Orleans 7 的持久化? Orleans 7 的持久化是指將 Or ...
  • 前言 .NET Feature Management 是一個用於管理應用程式功能的庫,它可以幫助開發人員在應用程式中輕鬆地添加、移除和管理功能。使用 Feature Management,開發人員可以根據不同用戶、環境或其他條件來動態地控制應用程式中的功能。這使得開發人員可以更靈活地管理應用程式的功 ...
  • 在 WPF 應用程式中,拖放操作是實現用戶交互的重要組成部分。通過拖放操作,用戶可以輕鬆地將數據從一個位置移動到另一個位置,或者將控制項從一個容器移動到另一個容器。然而,WPF 中預設的拖放操作可能並不是那麼好用。為瞭解決這個問題,我們可以自定義一個 Panel 來實現更簡單的拖拽操作。 自定義 Pa ...
  • 在實際使用中,由於涉及到不同編程語言之間互相調用,導致C++ 中的OpenCV與C#中的OpenCvSharp 圖像數據在不同編程語言之間難以有效傳遞。在本文中我們將結合OpenCvSharp源碼實現原理,探究兩種數據之間的通信方式。 ...
  • 一、前言 這是一篇搭建許可權管理系統的系列文章。 隨著網路的發展,信息安全對應任何企業來說都越發的重要,而本系列文章將和大家一起一步一步搭建一個全新的許可權管理系統。 說明:由於搭建一個全新的項目過於繁瑣,所有作者將挑選核心代碼和核心思路進行分享。 二、技術選擇 三、開始設計 1、自主搭建vue前端和. ...
  • Csharper中的表達式樹 這節課來瞭解一下表示式樹是什麼? 在C#中,表達式樹是一種數據結構,它可以表示一些代碼塊,如Lambda表達式或查詢表達式。表達式樹使你能夠查看和操作數據,就像你可以查看和操作代碼一樣。它們通常用於創建動態查詢和解析表達式。 一、認識表達式樹 為什麼要這樣說?它和委托有 ...
  • 在使用Django等框架來操作MySQL時,實際上底層還是通過Python來操作的,首先需要安裝一個驅動程式,在Python3中,驅動程式有多種選擇,比如有pymysql以及mysqlclient等。使用pip命令安裝mysqlclient失敗應如何解決? 安裝的python版本說明 機器同時安裝了 ...