【Cherno的C++视频】Vector-Making data structures 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"

// what does it actually take to write a vector class.

struct Vector3
{
	float x = 0.0f, y = 0.0f, z = 0.0f;
	int* m_MemoryBlock = nullptr;

	Vector3() { m_MemoryBlock = new int[5]; }

	Vector3(float scalar)
		:x(scalar), y(scalar), z(scalar)
	{
		m_MemoryBlock = new int[5];
	}

	Vector3(float x, float y, float z)
		:x(x), y(y), z(z)
	{
		m_MemoryBlock = new int[5];
	}

	Vector3(const Vector3& other) = delete;
	//	:x(other.x), y(other.y), z(other.z)
	//{
	//	std::cout << "struct Vector3 Copied!\n";
	//}

	Vector3(Vector3&& other)
		:x(other.x), y(other.y), z(other.z)
	{
		std::cout << "struct Vector3 Moved!\n";
		m_MemoryBlock = other.m_MemoryBlock;
		other.m_MemoryBlock = nullptr;
	}

	~Vector3()
	{
		std::cout << "struct Vector3 Destroyed\n";
		delete[] m_MemoryBlock;
	}

	Vector3& operator=(const Vector3& other) = delete;
	//{
	//	std::cout << "struct Vector3 operator= Copied!\n";
	//	x = other.x;
	//	y = other.y;
	//	z = other.z;
	//	return *this;
	//}

	Vector3& operator=(Vector3&& other)
	{
		std::cout << "struct Vector3 operator= Moved!\n";
		m_MemoryBlock = other.m_MemoryBlock;
		other.m_MemoryBlock = nullptr;

		x = other.x;
		y = other.y;
		z = other.z;
		return *this;
	}
};

template<typename T>
void PrintMyVector(const MyVector<T>& vector)
{
	for (size_t i = 0; i < vector.Size(); i++)
	{
		std::cout << vector[i] << std::endl;
	}
	std::cout << "-----------------------------" << std::endl;
}

template<>
void PrintMyVector(const MyVector<Vector3>& vector)
{
	for (size_t i = 0; i < vector.Size(); i++)
	{
		std::cout << vector[i].x << ", " << vector[i].y << ", " << vector[i].z << std::endl;
	}
	std::cout << "-----------------------------" << std::endl;
}

int main(void)
{
	MyVector<Vector3> data2;
	data2.PushBack(Vector3(1.0f));
	data2.PushBack(Vector3(2, 3, 4));
	data2.PushBack(Vector3());
	PrintMyVector(data2);

	MyVector<Vector3> data3;
	data3.EmplaceBack(1.0f);
	data3.EmplaceBack(2, 3, 4);
	data3.EmplaceBack();
	PrintMyVector(data3);

	MyVector<Vector3> data4;
	data4.EmplaceBack(1.0f);
	data4.EmplaceBack(2, 3, 4);
	data4.EmplaceBack(1, 3, 4);
	data4.EmplaceBack();
	PrintMyVector(data4);
	data4.PopBack();
	data4.PopBack();
	PrintMyVector(data4);
	data4.EmplaceBack(5, 2, 0);
	data4.EmplaceBack(1, 7, 9);
	PrintMyVector(data4);
	data4.Clear();
	PrintMyVector(data4);
	data4.EmplaceBack(5, 2, 0);
	data4.EmplaceBack(1, 7, 9);
	PrintMyVector(data4);
	PrintMyVector(data4);

	MyVector<int> data5;
	data5.PushBack(5);
	data5.EmplaceBack(2);
	data5.EmplaceBack(2);
	data5.EmplaceBack(2);
	data5.EmplaceBack(2);
	data5.EmplaceBack(2);
	PrintMyVector(data5);
	data5.PopBack();
	PrintMyVector(data5);
	data5.Clear();

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值