C++学习笔记 55 自定义Vector

#include<iostream>
#include<string>

template<typename T>
class Vector {

private:
	size_t m_Size = 0;
	size_t m_Capacity = 0;
	T* m_Data = nullptr;

public:
	Vector() {
		ReAlloc(2);
	}
	
	~Vector() {
		//清除内置数据空间
		//delete[] m_Data;

		//方法里会手动调用清除元素对象的析构函数
		clear();
		//删除对象时,不会调用对象的析构函数,将对象的析构函数的调用全部在clear() 函数中统一处理
		::operator delete(m_Data, m_Capacity * sizeof(T));
	}

	//添加数据
	void PushBack(const T& value) {
		if (m_Size >= m_Capacity)
			ReAlloc(m_Capacity + m_Capacity / 2);
		
		// = 操作符被删除时,此句不可用, 教学视频中可用,此处打问号❓️
		//m_Data[m_Size] = value;
		//自定义适配
		m_Data[m_Size] = (T&&)value;
		m_Size++;
	}

	//移动数据,不涉及到copy,注意:临时变量前面不能+ const
	void PushBack(T&& value) {
		if (m_Size >= m_Capacity)
			ReAlloc(m_Capacity + m_Capacity / 2);
		
		m_Data[m_Size++] = std::move(value);
	}

	//可变参数元素添加
	template<typename... Args>
	T& EmplaceBack(Args&&... args) {
		if (m_Size >= m_Capacity) {
			ReAlloc(m_Capacity + m_Capacity / 2);
		}

		//这个性能更优越,不会调用move= ! 和 Destroy !
		new(&m_Data[m_Size]) T(std::forward<Args>(args)...);
		//这个会调用一次:move= ! 和 Destroy !
		//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;
	}

	size_t Size() const { return m_Size; }

	const T& operator[] (size_t index) const {
		if (index >= m_Size) {
			//assert();
		}
		return m_Data[index];
	}

	T& operator[] (size_t index) {
		if (index >= m_Size) {
			//assert();
		}
		return m_Data[index];
	}

private:
	//重新分配内存,所以,无论新的size是 > < = ,都将reSize
	void ReAlloc(size_t newCapacity) {
		//1. allocate a new block of memory
		//2. copy/move old block elements
		//3. delete old elements

		//T* newBlock = new T[newCapacity];
		// 
		// 这里没必要调用构造函数,只需要分配空间即可。我们不用C语言的malloc (), 而是C++的 ::operator new
		//创建对象时不会调用构造函数
		T* newBlock = (T*)::operator new(newCapacity * sizeof(T));

		//如果新的容量大小 < 现有数据大小,则将现有数据大小切小
		if (newCapacity < m_Size)
			m_Size = newCapacity;

		//这里使用for loop 而不是memcopy是因为:我们需要用到复制构造函数,如果是原始数据类型,用memcopy OK,但是复杂类型:class, struct 则会导致深拷贝。
		//而我们确认调用了那个copy structure (复制构造函数),否则复杂类型无法正确地复制构造。
		for (size_t i = 0; i < m_Size; i++) {
			newBlock[i] = std::move(m_Data[i]);
		}
		//delete[] m_Data;
		//clear(); //不可用clear(), 因为此方法里将 m_Size 清零了
		for (size_t i = 0; i < m_Size; i++)
			m_Data[i].~T();

		//::operator delete时不会调用对象的析构函数
		::operator delete(m_Data, m_Capacity * sizeof(T));
		m_Data = newBlock;
		m_Capacity = newCapacity;
	}
};


struct Vector3 {
public:
	float x = 0.0f, y = 0.0f, z = 0.0f;
	//指针类型数据,可能会导致Vector的delete出现问题
	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) : x(other.x), y(other.y), z(other.z), m_memoryBlock(other.m_memoryBlock) {
	//	std::cout << "Copy ! \n";
	//}
	Vector3(const Vector3& other) = delete;
	//删除复制构造函数,避免复制(m_memoryBlock时)
	

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

	~Vector3() {
		std::cout << "Destroy ! \n";
		delete[] m_memoryBlock;
	}

	//Vector3& operator=(const Vector3& other) {
	//	std::cout << "Copy= ! \n";
	//	x = other.x;
	//	y = other.y;
	//	z = other.z;
	//  m_memoryBlock = other.m_memoryBlock;
	//	return *this;
	//}
	Vector3& operator=(const Vector3& other) = delete;
	//删除复制赋符号函数,避免复制(m_memoryBlock时)


	Vector3& operator=(Vector3&& other) {
		std::cout << "move= ! \n";
		x = other.x;
		y = other.y;
		z = other.z;

		m_memoryBlock = other.m_memoryBlock;
		other.m_memoryBlock = nullptr;
		return *this;
	}
};


void PrintVector3(Vector<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;
}


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

//1. 标准库基础类元素测试
void testStdType() {
	Vector<std::string> vector;
	vector.PushBack("Hello");
	vector.PushBack("World");
	vector.PushBack("Hello World");
	PrintVector(vector);
}

//2. 自定义类构造函数
void testSelfDefineTypePushBack() {
	Vector<Vector3> vector0;
	vector0.PushBack(Vector3(1.2f));
	vector0.PushBack(Vector3(1.2f, 2.3f, 3.4f));
	vector0.PushBack(Vector3());
	PrintVector3(vector0);
}

//3. 自定义类可变参数批量方式
void testSelfDefineTypeEmplaceBack() {
	Vector<Vector3> vector1;
	vector1.EmplaceBack(1.2f);
	vector1.EmplaceBack(2, 3, 4);
	vector1.EmplaceBack();
	PrintVector3(vector1);
}

//4. 自定义类可变参数批量方式
void testSelfDefineTypePopBackClear() {
	{
		Vector<Vector3> vector3;
		vector3.EmplaceBack(1.0f);
		vector3.EmplaceBack(2, 3, 4);
		vector3.EmplaceBack(1, 3, 4);
		vector3.EmplaceBack();
		PrintVector3(vector3);
		vector3.PopBack();
		vector3.PopBack();
		vector3.EmplaceBack(5, 2, 0);
		vector3.EmplaceBack(1, 7, 9);
		PrintVector3(vector3);

		vector3.clear();
		PrintVector3(vector3);
		vector3.EmplaceBack(5, 2, 0);
		vector3.EmplaceBack(1, 7, 9);
		PrintVector3(vector3);
	}
}


int main() {
	testSelfDefineTypePopBackClear();
	std::cin.get();
}

wandbox验证

posted @ 2026-01-05 16:11  超轶绝尘  阅读(4)  评论(0)    收藏  举报