【Cherno的C++视频】Writing iterators in C++

MyVector.h

#pragma once

template<typename MyVector>
class MyVectorIterator
{
public:
	using ValueType = typename MyVector::ValueType;
	using PointerType = ValueType*;
	using ReferenceType = ValueType&;
public:
	MyVectorIterator(PointerType ptr)
		:m_Ptr(ptr) {}

	MyVectorIterator& operator++()
	{
		m_Ptr++;
		return *this;
	}

	MyVectorIterator operator++(int)
	{
		MyVectorIterator iterator = *this;
		++(*this);
		return iterator;
	}

	MyVectorIterator& operator--()
	{
		m_Ptr--;
		return *this;
	}

	MyVectorIterator operator--(int)
	{
		MyVectorIterator iterator = *this;
		--(*this);
		return iterator;
	}

	ReferenceType operator[](int index)
	{
		return *(m_Ptr + index);
	}

	PointerType operator->()
	{
		return m_Ptr;
	}

	ReferenceType operator*()
	{
		return *m_Ptr;
	}

	ReferenceType operator*(int)
	{
		return *m_Ptr;
	}

	bool operator==(const MyVectorIterator& other) const
	{
		return m_Ptr == other.m_Ptr;
	}

	bool operator!=(const MyVectorIterator& other) const
	{
		return !(*this == other);
	}
private:
	PointerType m_Ptr;
};

template<typename T>
class MyVector
{
public:
	using ValueType = T;
	using Iterator = MyVectorIterator<MyVector<T>>;
public:
	MyVector()
	{
		//allocate 2 elements
		ReAlloc(2);
	}

	void PushBack(const T& value)
	{
		if (m_Size >= m_Capacity)
		{
			ReAlloc(m_Capacity * 2);//double it.
		}
		m_Data[m_Size] = value;
		m_Size++;
	}
	// to avoid data copy
	void PushBack(T&& value)
	{
		if (m_Size >= m_Capacity)
		{
			ReAlloc(m_Capacity * 2);
		}
		m_Data[m_Size] = std::move(value);
		m_Size++;
	}

	size_t Size() const { return m_Size; }

	template<typename...Args>
	T& EmplaceBack(Args&&... args)
	{
		if (m_Size >= m_Capacity)
		{
			ReAlloc(m_Capacity * 2);
		}
		// new() -> advanced tip of the day, for constructing objects in that place.
		new(&m_Data[m_Size]) T(std::forward<Args>(args)...);//better than:m_Data[m_Size] = T(std::forward<Args>(args)...);
		return m_Data[m_Size++];
	}

	void PopBack()
	{
		if (m_Size > 0)
		{
			m_Size--;
			m_Data[m_Size].~T();
		}
	}

	void Clear()
	{
		for (size_t i = 0; i < m_Size; i++)
		{
			m_Data[i].~T();
		}
		m_Size = 0;
	}

	const T& operator[] (size_t index) const
	{
		//size check for debug mode.
		if (index >= m_Size)
		{
			__debugbreak();
		}
		return m_Data[index];
	}

	T& operator[] (size_t index)
	{
		//size check for debug mode.
		if (index >= m_Size)
		{
			__debugbreak();
		}
		return m_Data[index];
	}

	~MyVector()
	{
		Clear();
		std::cout << "class MyVector destroyed!\n";
		//delete[] m_Data;
		::operator delete(m_Data, m_Capacity * sizeof(T));//::operator delete won't call any destructors.
		
		
	}

	Iterator begin()
	{
		return Iterator(m_Data);
	}

	Iterator end()
	{
		return Iterator(m_Data + m_Size);
	}
private:
	void ReAlloc(size_t newCapacity)
	{
		// allocate a new block of memory
		//T* newBlock = new T[newCapacity];//raw pointer->to access memory as low level as we can.
		T* newBlock = (T*) ::operator new(newCapacity * sizeof(T));//operator new() won't call any constructor.

		//downsize or upsize
		if (newCapacity < m_Size)
		{
			m_Size = newCapacity;
		}

		// move old elements into the new memory by using a for loop bc need to be 
		// hitting the copy constructor of all of these elements.
		// memcpy() for simple types:int float.
		for (size_t i = 0; i < m_Size; i++)
		{
			//newBlock[i] = std::move(m_Data[i]);
			new (&newBlock[i]) T(std::move(m_Data[i]));
		}

		// clear
		for (size_t i = 0; i < m_Size; i++)
		{
			m_Data[i].~T();
		}

		// delete the old block.
		::operator delete(m_Data, m_Capacity * sizeof(T));// delete[] m_Data;
		
		m_Data = newBlock;
		m_Capacity = newCapacity;
	}
private:
	T* m_Data = nullptr;
	size_t m_Size = 0;//the number of element.
	size_t m_Capacity = 0;//how much memory we have allocated.
};

main.cpp

#include <iostream>
#include <string>
#include "MyVector.h"

int main(void)
{
	MyVector<int> intValues;
	intValues.EmplaceBack(1);
	intValues.EmplaceBack(2);
	intValues.EmplaceBack(3);
	intValues.EmplaceBack(4);
	intValues.EmplaceBack(5);

	MyVector<std::string> strValues;
	strValues.EmplaceBack("1");
	strValues.EmplaceBack("2");
	strValues.EmplaceBack("IamGroot");
	strValues.EmplaceBack("4");
	strValues.EmplaceBack("5");

	std::cout << "---------Not using iterators:---------\n";
	for (int i = 0; i < strValues.Size(); i++)
	{
		std::cout << strValues[i] << std::endl;
	}
	std::cout << "---------range-based for loop:---------\n";
	for (auto& value : strValues)
	{
		std::cout << value << std::endl;
	}
	std::cout << "---------iterators:---------\n";
	for (MyVector<std::string>::Iterator it = strValues.begin(); it != strValues.end(); it++)
	{
		std::cout << *it << std::endl;
	}

	std::cin.get();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值