C++的STL库中提供了很多数据结构,用起来很方便,但了解底层原理也是很重要的,它可以帮助我们提高编程水平。本人最近就模仿STL制作了一个vector容器。代码如下:
#pragma once
#include<stdexcept>
template<typename type>
class CVector
{
public:
//迭代器类
class CIterator
{
public:
//构造函数
CIterator()noexcept;
CIterator(type* p)noexcept;
CIterator(const CIterator& i)noexcept;
//运算符重载
type& operator*()const;
CIterator& operator++();
CIterator& operator--();
CIterator operator++(int);
CIterator operator--(int);
CIterator operator+(int offset)const;
CIterator operator-(int offset)const;
CIterator& operator+=(int offset);
CIterator& operator-=(int offset);
size_t operator-(const CIterator& iter);
type& operator[](int offset);
friend auto operator<=>(const CIterator& a, const CIterator& b) = default;
private:
type* m_p;
};
//构造函数
CVector()noexcept;
CVector(size_t nSize);
CVector(size_t nSize, const type& t);
CVector(const CVector& t);
CVector(CIterator Begin, CIterator End);
//随机访问函数
type& operator[](size_t index)const;
type& At(size_t index)const;
type& Front()const;
type& Back()const;
size_t FindFirst(const type& t)const;
size_t FindLast(const type& t)const;
CIterator Begin()const noexcept;
CIterator End()const noexcept;
//修改函数
void PushBack(const type& t);
void PopBack()noexcept;
void Erase(size_t nPos);
void Erase(size_t nPos, size_t count);
void Insert(size_t nPos, const type& t);
void Insert(size_t nPos, size_t count, const type& t);
void Clear()noexcept;
void Swap(CVector& v)noexcept;
CVector<type>& operator=(const CVector& t);
//容器信息函数
size_t Size()const noexcept;//实际元素个数
size_t Capacity()const noexcept;//当前内存所能容纳的最多元素个数
bool Empty()const noexcept;//判断是否为空
bool operator==(const CVector& v)const noexcept;
bool operator!=(const CVector& v)const noexcept;
//析构函数
~CVector();
private:
void SetMem(size_t t = 64);
type* m_data;
size_t m_size;//实际元素个数
size_t m_len;//内存长度
};
template<typename type>
CVector<type>::CVector()noexcept
:m_data(nullptr), m_len(0), m_size(0)
{
}
template<typename type>
CVector<type>::CVector(size_t nSize)
: m_data(new type[nSize]()), m_len(nSize), m_size(nSize)
{
}
template<typename type>
CVector<type>::CVector(size_t nSize, const type& t)
: m_data(new type[nSize]), m_len(nSize), m_size(nSize)
{
for (size_t i = 0; i < nSize; i++)
m_data[i] = t;
}
template<typename type>
CVector<type>::CVector(const CVector& t)
: m_data(new type[t.m_len]), m_len(t.m_len), m_size(t.m_size)
{
for (size_t i = 0; i < t.m_size; i++)
m_data[i] = t.m_data[i];
}
template<typename type>
CVector<type>::CVector(CIterator Begin, CIterator End) :m_size(End - Begin), m_len(m_size), m_data(new type[End - Begin])
{
for (size_t i = 0; i < m_size; i++)
m_data[i] = *Begin++;
}
template<typename type>
size_t CVector<type>::Size() const noexcept
{
return m_size;
}
template<typename type>
size_t CVector<type>::Capacity() const noexcept
{
return m_len;
}
template<typename type>
bool CVector<type>::Empty() const noexcept
{
return !m_size;
}
template<typename type>
bool CVector<type>::operator==(const CVector& v)const noexcept
{
if (this->m_size != v.m_size)
return false;
for (size_t i = 0; i < m_size; i++)
{
if (this->At(i) != v.At(i))
return false;
}
return true;
}
template<typename type>
bool CVector<type>::operator!=(const CVector& v) const noexcept
{
return !(this->operator==(v));
}
template<typename type>
void CVector<type>::Swap(CVector& v)noexcept
{
type* temp = m_data;
m_data = v.m_data;
v.m_data = temp;
size_t t = m_size;
m_size = v.m_size;
v.m_size = t;
t = m_len;
m_len = v.m_len;
v.m_len = t;
}
template<typename type>
CVector<type>& CVector<type>::operator=(const CVector& t)
{
if (m_len < t.m_size)
{
SetMem(t.m_size + 64);
}
m_size = t.m_size;
for (size_t i = 0; i < t.m_size; i++)
m_data[i] = t.m_data[i];
return *this;
}
template<typename type>
type& CVector<type>::operator[](size_t index)const
{
if (index >= m_size)
throw std::out_of_range("下标越界!");
return m_data[index];
}
template<typename type>
type& CVector<type>::At(size_t index) const
{
if (index >= m_size)
throw std::out_of_range("下标越界!");
return m_data[index];
}
template<typename type>
type& CVector<type>::Front() const
{
if (m_size == 0)
throw std::out_of_range("容器为空!");
return m_data[0];
}
template<typename type>
type& CVector<type>::Back() const
{
if (m_size == 0)
throw std::out_of_range("容器为空!");
return m_data[m_size - 1];
}
template<typename type>
size_t CVector<type>::FindFirst(const type& t)const
{
for (size_t i = 0; i < m_size; i++)
{
if (m_data[i] == t)
return i;
}
return -1;
}
template<typename type>
size_t CVector<type>::FindLast(const type& t)const
{
for (int i = m_size - 1; i >= 0; i--)
{
if (m_data[i] == t)
return i;
}
return -1;
}
template<typename type>
CVector<type>::CIterator CVector<type>::Begin() const noexcept
{
return CIterator(m_data);
}
template<typename type>
CVector<type>::CIterator CVector<type>::End() const noexcept
{
return CIterator(m_data + m_size);
}
template<typename type>
void CVector<type>::PushBack(const type& t)
{
if (m_size == m_len)//容器已满
{
SetMem(m_size + 64);
}
m_data[m_size++] = t;
}
template<typename type>
void CVector<type>::PopBack()noexcept
{
if (m_size != 0)
m_size--;
}
template<typename type>
void CVector<type>::Erase(size_t nPos)
{
if (nPos >= m_size)
throw std::out_of_range("下标越界!");
for (size_t i = nPos + 1; i < m_size; i++)
m_data[i - 1] = m_data[i];
m_size--;
}
template<typename type>
void CVector<type>::Erase(size_t nPos, size_t count)
{
if (nPos + count - 1 >= m_size)
throw std::out_of_range("下标越界!");
for (size_t i = nPos + count; i < m_size; i++)
m_data[i - count] = m_data[i];
m_size -= count;
}
template<typename type>
void CVector<type>::Insert(size_t nPos, const type& t)
{
if (nPos >= m_size)
throw std::out_of_range("下标越界!");
if (m_size == m_len)//容器已满
{
SetMem(m_size + 64);
}
for (size_t i = nPos; i < m_size; i++)
m_data[i + 1] = m_data[i];
m_data[nPos] = t;
m_size++;
}
template<typename type>
void CVector<type>::Insert(size_t nPos, size_t count, const type& t)
{
if (nPos >= m_size)
throw std::out_of_range("下标越界!");
if (m_size + count > m_len)
{
SetMem(m_size + count + 64);
}
for (size_t i = nPos; i < m_size; i++)
m_data[i + count] = m_data[i];
for (size_t i = nPos; i < nPos + count; i++)
m_data[i] = t;
m_size += count;
}
template<typename type>
void CVector<type>::Clear()noexcept
{
m_size = 0;
}
template<typename type>
CVector<type>::~CVector()
{
if (m_data != nullptr)
delete[]m_data;
}
template<typename type>
void CVector<type>::SetMem(size_t t)
{
type* temp = new type[m_len];
for (size_t i = 0; i < m_size; i++)
temp[i] = m_data[i];
if (m_data != nullptr)
delete[] m_data;
m_data = new type[m_len = t];
for (size_t i = 0; i < m_size; i++)
m_data[i] = temp[i];
delete[] temp;
}
template<typename type>
CVector<type>::CIterator::CIterator()noexcept :m_p(nullptr)
{
}
template<typename type>
CVector<type>::CIterator::CIterator(type* p)noexcept : m_p(p)
{
}
template<typename type>
CVector<type>::CIterator::CIterator(const CVector<type>::CIterator& i)noexcept : m_p(i.m_p)
{
}
template<typename type>
type& CVector<type>::CIterator::operator*()const
{
return *m_p;
}
template<typename type>
CVector<type>::CIterator& CVector<type>::CIterator::operator++()
{
m_p++;
return *this;
}
template<typename type>
CVector<type>::CIterator& CVector<type>::CIterator::operator--()
{
m_p--;
return *this;
}
template<typename type>
CVector<type>::CIterator CVector<type>::CIterator::operator++(int)
{
CIterator temp(*this);
m_p++;
return temp;
}
template<typename type>
CVector<type>::CIterator CVector<type>::CIterator::operator--(int)
{
CIterator temp(*this);
m_p--;
return temp;
}
template<typename type>
CVector<type>::CIterator CVector<type>::CIterator::operator+(int offset)const
{
return CIterator(this->m_p + offset);
}
template<typename type>
CVector<type>::CIterator CVector<type>::CIterator::operator-(int offset)const
{
return CIterator(this->m_p - offset);
}
template<typename type>
CVector<type>::CIterator& CVector<type>::CIterator::operator+=(int offset)
{
m_p += offset;
return *this;
}
template<typename type>
CVector<type>::CIterator& CVector<type>::CIterator::operator-=(int offset)
{
m_p -= offset;
return *this;
}
template<typename type>
size_t CVector<type>::CIterator::operator-(const CIterator& iter)
{
return this->m_p - iter.m_p;
}
template<typename type>
type& CVector<type>::CIterator::operator[](int offset)
{
return *(operator+(offset));
}