#pragma once
#include <cstdint>
#include <memory>
#include <stdexcept>
#include <functional>
template <typename T>
class List
{
public:
//无参构造函数
explicit List();
//拷贝构造函数
List(const List& other);
//移动构造函数
List(List&& other);
//虚析构器 确保子类对象删除
virtual ~List();
public:
//添加元素 data
void push_back(const T& data);
//删除末尾元素
void pop_back();
//释放内存
void clear();
//返回指定索引的值
T& at(size_t index);
//返回指定索引的值 只读操作
const T& at(size_t index) const;
//列表中元素的数量
size_t size() const;
public:
//返回两个元素是否相等
bool operator==(const List<T>& other);
//返回两个元素是否不相等
bool operator!=(const List<T>& other);
//赋值:将另一个List对象赋值给当前对象
List<T>& operator=(const List<T>& other);
//加:两个List相加 返回一个新的List对象
List<T>& operator+(const List<T>& other);
//[]:返回指定索引的值
T& operator[](size_t index);
const T& operator[](size_t index)const;
private:
//指向列表数据的指针
T* datas;
//存储的数量
int64_t data_size;
};
//赋值 nullptr 元素数量0
template<typename T>
inline List<T>::List()
: datas(nullptr), data_size(0)
{
}
//拷贝构造:
template<typename T>
inline List<T>::List(const List& other)
{
//清空List的数据
clear();
//获取other列表中元素数量
data_size = other.data_size;
//申请内存 datas = new T[data_size];
datas = (T*)malloc(sizeof(T) * data_size);
//复制到新的列表中
for (size_t i = 0; i < data_size; ++i)
{
datas[i] = other.datas[i];
}
}
//移动构造
template<typename T>
inline List<T>::List(List&& other)
{
//other的指针
datas = other.datas;
//other的元素数量给data_size
data_size = other.data_size;
//赋空值
other.datas = nullptr;
other.data_size = 0;
}
//释放内存
template<typename T>
inline List<T>::~List()
{
clear();
}
//添加元素
template<typename T>
inline void List<T>::push_back(const T& data)
{
//datas指向的内存块有数据存在
if (datas != nullptr)
{
//重新分配内存以容纳新的元素
T* tmp_ptr = (T*)realloc(datas, sizeof(T) * (data_size + 1));
if (tmp_ptr)
{
//更新内存指针,指向新的内存块
datas = tmp_ptr;
//定位到新分配内存的位置
T& tmp_data = *(datas + data_size);
//将data拷贝到这个位置上
new(&tmp_data) T(data);
}
}
//第一次插入数据
else
{
//分配内存
datas = (T*)malloc(sizeof(T));
//将data拷贝到这个位置上
new(datas) T(data);
}
//元素个数+1
++data_size;
}
//删除
template<typename T>
inline void List<T>::pop_back()
{
//没有元素
if (data_size == 0)
{
return;
}
//元素为1
else if (data_size == 1)
{
//调用析构器销毁最后一个元素 使用malloc 和 realloc 动态分配内存 手动释放
datas->~T();
//释放分配给datas的内存
free(datas);
datas = nullptr;
//元素个数-1
--data_size;
}
//元素大于1
else if (data_size > 1)
{
//调用析构器销毁最后一个元素
datas[data_size - 1]->~T();
//使用realloc减少datas指针指向的内存块大小 将其缩小为原来的data_size-1
T* tmp_ptr = (T*)realloc(datas, sizeof(T) * (data_size - 1));
//如果成功 将指针datas指向新的内存块
if (tmp_ptr) datas = tmp_ptr;
--data_size;
}
}
//释放内存
template<typename T>
inline void List<T>::clear()
{
if (datas)
{
free(datas);
datas = nullptr;
data_size = 0;
}
}
//返回指定索引的值
template<typename T>
inline T& List<T>::at(size_t index)
{
//索引超出范围 抛出异常
if (index >= data_size)
throw std::runtime_error("栈溢出");
return datas[index];
}
template<typename T>
inline const T& List<T>::at(size_t index) const
{
if (index >= data_size)
throw std::runtime_error("栈溢出");
return datas[index];
}
//元素数量
template<typename T>
inline size_t List<T>::size() const
{
return data_size;
}
//返回两个List是否相等
template<typename T>
inline bool List<T>::operator==(const List<T>& other)
{
//判断List的长度是否相等
if (data_size != other.data_size) return false;
//判断每个元素是否相等
for (size_t i = 0; i < data_size; ++i)
{
if (datas[i] != other.datas[i])
return false;
}
return true;
}
//返回两个List是否不相等
template<typename T>
inline bool List<T>::operator!=(const List<T>& other)
{
return !operator==(other);
}
//赋值:将另一个List对象赋值给当前对象
template<typename T>
inline List<T>& List<T>::operator=(const List<T>& other)
{
//清空List
clear();
//获取other元素数量
data_size = other.data_size;
//分配内存
datas = (T*)malloc(sizeof(T) * data_size);
//将other的数据复制给datas
for (size_t i = 0; i < data_size; ++i)
{
datas[i] = other.datas[i];
}
//返回当前对象的引用
return *this;
}
//两个链表相加
template<typename T>
inline List<T>& List<T>::operator+(const List<T>& other)
{
//result指向当前对象
List<T>& result = *this;
//不执行
while (true)
{
//other是否为空
if (other.data_size == 0 || other.datas == nullptr)
break;
//分配内存:内存大小:data_size + other.data_size
T* tmp_ptr = (T*)realloc(datas, data_size + other.data_size);
if (!tmp_ptr)
break;
//datas指向新分配的内存
datas = tmp_ptr;
//将other List中的数据追加到当前的List的末尾
for (size_t i = 0; i < other.data_size; ++i)
{
datas[data_size + i] = other.datas[i];
}
data_size += other.data_size;
}
return result;
}
//重载[]:访问List中的数据
template<typename T>
inline T& List<T>::operator[](size_t index)
{
if (index >= data_size)
throw std::runtime_error("栈溢出");
return datas[index];
}
template<typename T>
inline const T& List<T>::operator[](size_t index) const
{
if (index >= data_size)
throw std::runtime_error("栈溢出");
return datas[index];
}
#include <iostream>
#include "List.hpp"
#include <string>
int main(int argc, char* argv[])
{
//创建test_list_1对象
List<std::string> test_list_1;
//添加元素
test_list_1.push_back("abc");
test_list_1.push_back("def");
test_list_1.push_back("123");
for (size_t i = 0; i < test_list_1.size(); ++i)
{
//通过[]访问元素
std::string& str = test_list_1[i];
std::cout << str << std::endl;
}
//创建test_list_2对象
List<int> test_list_2;
//添加元素
test_list_2.push_back(1);
test_list_2.push_back(2);
test_list_2.push_back(3);
for (size_t i = 0; i < test_list_2.size(); ++i)
{
//通过[]访问元素
int& num = test_list_2[i];
std::cout << num << std::endl;
}
return 0;
}