namespace no_size_t_para
{
template <typename T>
class Array
{
public:
using value_type = T;
using size_type = size_t;
using pointer = T*;
using const_pointer = const T*;
using reference = T&;
using const_reference = const T&;
Array();
Array(size_t size);
~Array();
Array(const Array&);
T& operator[]( size_t index);
const T& operator[](const size_t index)const;
Array& operator=(const Array& copy);
size_t GetSize()const
{
return m_size;
}
bool Swap(Array& other);
private:
T* m_element;
size_t m_size;
};
template <typename T>
Array<T>::Array()
{}
template <typename T>
Array<T>::Array(size_t size) :m_element(new T[size]), m_size(size)
{
if (m_element == nullptr)
std::cout << "申请空间失败" << std::endl;
}
// Copy constructor template
template <typename T>
Array<T>::Array(const Array& Copy)
{
m_size = Copy.GetSize();
m_element = new T[m_size];
if (m_element == nullptr)
std::cout << "申请空间失败" << std::endl;
for (int i = 0; i < m_size; ++i)
{
m_element[i] = Copy.m_element[i];
}
}
template <typename T>
Array<T>::~Array()
{
delete[]m_element;
m_element = nullptr;
m_size = ZERO;
}
//const subscript operator template
template <typename T>
const T& Array<T>::operator[](size_t index) const
{
if (index >= m_size)
throw std::out_of_range{ "Index too large: " + std::to_string(index) };
//std::cout << typeid(m_element[index]).name();
return m_element[index];
}
template <typename T>
T& Array<T>::operator[](const size_t index)
{
const Array& constarray = std::as_const(*this);
//下面是利用了const operator[]重载函数,避免代码重复编写,遵循代码可复用
const T& constresult = constarray[index];//如果没const版operator[]重载函数无法编译通过
return const_cast<T&>(constresult);
//return const_cast<T&>(std::as_const(*this)[index]);
}
template <typename T>
Array<T>& Array<T>::operator=(const Array& rhs)
{
Array<T> copy{ rhs };
Swap(copy);
return *this;
}
template <typename T>
bool Array<T>::Swap(Array& other)
{
std::swap(m_element, other.m_element);
std::swap(m_size, other.m_size);
return true;
}
}
笔记:
1.通过下标运算符的重载函数学习到代码中的异常安全性和防止异常安全性的行为:复制后交换技术。
2.通过下标运算符的重载函数学习到代码的复用,在非const 版本函数中复用了const版本 下标运算符的重载;
3.编译器调动下标运算符的重载函数的const 和非const版本:opertor[]const this 饰词如果是const 则调动const 版下标运算符,也就是const 对象会调动这个版本的重载。
4. 拷贝构造还可以写成这种形式:调动了构造函数
// Copy constructor template
template <typename T>
Array<T>::Array(const Array& array) : Array{array.m_size}
{
for (size_t i {}; i < m_size; ++i)
m_elements[i] = array.m_elements[i];
}
5.理解了auto 型别推导 :和模板型别推导类似:其实就是auto 对应的是T。