最近新到公司,带教老师让我写动态数组,哇,给我的感觉真的是,底层的东西,要求性能和代码规范比较严,下面是代码。
我会写很详细的注释,方便以后自己观看。希望各位请教了。
MyArray.h
#ifndef MYARRAY_H
#define MYARRAY_H
#include <iostream>
//函数后面加const表示函数不改变类中的成员变量
//参数里面加const &表示参数是值传递,省去零时对象的构建和析构
class MyArray
{
public:
MyArray(); // 默认构造函数
MyArray(const int& nSize, double dValue = 0); //构造函数,设置数组的大小,默认值为dValue
MyArray(const MyArray& arr); //拷贝构造函数
MyArray& operator=(const MyArray& arr); //拷贝赋值构造函数
virtual ~MyArray(); //析构函数
void print(); //打印输出
void swap(MyArray & arr); //交换
double front(); //返回第一个值
void clear(); //清空数组
int GetSize() const; //获取数组的大小
void SetSize(const int& nSize); //重新设置数组的大小
double GetAt(const int& nIndex) const; //获取指定位置的元素
void SetAt(const int& nIndex, const double& dValue); //重置指定位置元素的值
void PushBack(const double& dValue); //追加一个元素到数组的末尾
void DeleteAt(const int& nIndex); //删除指点位置的元素
void InsertAt(const int& nIndex, const double& dValue); //插入一个新的元素到指定的位置
double operator[](const int& nIndex) const; // 重载下标运算符
private:
void Init(); //初始化
void Free(); //释放动态指针
inline bool InvalidateIndex(const int& nIndex) const; //判断下标的合法性,false是有效的,true是无效的
private:
std::wstring str;
double *m_Data; //存放数组的动态内存指针
int m_Size; //数组的元素个数
int m_Max; //预留给动态数组的内存大小
};
#endif // MYARRAY_H
MyArray.cpp
#include "stdafx.h"
#include "myarray.h"
void MyArray::Init()
{
m_Size = 0;
m_Max = 1;
m_Data = new double[m_Max];
}
void MyArray::Free()
{
delete[] m_Data;
}
bool MyArray::InvalidateIndex(const int& nIndex) const
{
if (nIndex >= 0 && nIndex < m_Size)
{
return false;
}
else
{
return true;
}
}
//默认构造函数
MyArray::MyArray()
{
Init();
}
//
MyArray::MyArray(const int& nSize, double dValue)
{
if (nSize == 0)
{
Init();
}
else
{
m_Size = nSize;
m_Max = nSize;
m_Data = new double[m_Max];
for (int i = 0;i < nSize; ++i)
{
m_Data[i] = dValue;
}
}
}
MyArray::MyArray(const MyArray& arr)
{
m_Size = arr.m_Size;
m_Max = arr.m_Max;
m_Data = new double[m_Max];
memcpy(m_Data, arr.m_Data, m_Size * sizeof(m_Data[0]));
}
MyArray& MyArray::operator = (const MyArray& arr)
{
if (this == &arr) //判断自赋值
return *this;
m_Size = arr.m_Size;
m_Max = arr.m_Max;
//深拷贝,浅拷贝的问题
double* m_Temp = new double[m_Max];
memcpy(m_Temp, arr.m_Data, m_Size * sizeof(m_Data[0]));
delete[] m_Data;
m_Data = m_Temp;
return *this;
}
MyArray::~MyArray()
{
Free();
}
void MyArray::print()
{
for (int i = 0; i < m_Size; ++i)
{
std::cout << m_Data[i] << std::endl;
}
}
void MyArray::swap(MyArray& arr)//通过异或来进行地址的直接操作
{
//和标准库里面是一样的,但是有问题是会有两次深拷贝,性能上是损失的
/*MyArray temp(arr);
arr = *this;
*this = temp;*/
//通过异或作用符来进行位运算,没有深拷贝的问题,性能提升,但是当有对象在类中的时候,好像不行
//reinterpret_cast强制类型转换符
unsigned char* pArr = reinterpret_cast<unsigned char*>(&arr);
unsigned char* pThis = reinterpret_cast<unsigned char*>(&(*this));
for (unsigned char x = 0; x < sizeof(MyArray); ++x)
{
pArr[x] ^= pThis[x];
pThis[x] ^= pArr[x];
pArr[x] ^= pThis[x];
}
//通过浅拷贝来提升性能
//MyArray temp = std::move(arr);
//arr = std::move(*this);
//*this = std::move(temp);
/*
//一样的通过浅拷贝来提升性能
MyArray temp;
temp.m_Data = arr.m_Data;
temp.m_Size = arr.m_Size;
temp.m_Max = arr.m_Max;
arr.m_Data = this->m_Data;
arr.m_Size = this->m_Size;
arr.m_Max = this->m_Max;
this->m_Data = temp.m_Data;
this->m_Size = temp.m_Size;
this->m_Max = temp.m_Max;*/
}
double MyArray::front()
{
return m_Data[0];
}
void MyArray::clear()
{
delete[] m_Data;
m_Data = NULL;
m_Size = 0;
m_Max = 0;
}
int MyArray::GetSize() const
{
return m_Size;
}
void MyArray::SetSize(const int& nSize)
{
if (nSize > m_Max)
{
m_Max = nSize; // 先将最大值修改成所修改的
double *temp = new double[m_Max]; // 然后new一个中间的数组来保存之前,数组大小是新的
memcpy(temp, m_Data, m_Size * sizeof(m_Data[0]));
delete[] m_Data; // 删除老的
m_Data = temp; // 然后赋值,深拷贝
}
m_Size = nSize;
}
double MyArray::GetAt(const int& nIndex) const
{
if (InvalidateIndex(nIndex))
{
throw std::out_of_range("Error:the index out of range");
}
return m_Data[nIndex];
}
void MyArray::SetAt(const int& nIndex, const double& dValue)
{
if (InvalidateIndex(nIndex))
{
throw std::out_of_range("Error:the index out of range");
}
else
{
m_Data[nIndex] = dValue;
}
}
void MyArray::PushBack(const double& dValue)
{
InsertAt(m_Size, dValue);
}
//删除一个元素
void MyArray::DeleteAt(const int& nIndex)
{
if (InvalidateIndex(nIndex))
{
throw std::out_of_range("Error:the index out of range");
}
else
{
memcpy(&m_Data[nIndex], &m_Data[nIndex + 1], (m_Size - nIndex - 1) * sizeof(m_Data[0]));//将后面的值依次给前面的,不用for循环,提升性能
--m_Size;
}
}
void MyArray::InsertAt(const int& nIndex, const double& dValue)
{
if (nIndex < 0 || nIndex > m_Size)
{
throw std::out_of_range("Error:the index out of range");
}
if (m_Size < m_Max) // 还没满,可以直接插入
{
memcpy(&m_Data[m_Size], &m_Data[m_Size - 1], (m_Size - 1 - nIndex) * sizeof(m_Data[0]));
m_Data[nIndex] = dValue;
}
else
{
m_Max = m_Max * 2;
double *temp = new double[m_Max];
memcpy(temp, m_Data, m_Size * sizeof(m_Data[0]));
delete[] m_Data;
m_Data = temp;
m_Data[m_Size] = dValue;
}
++m_Size;
}
double MyArray::operator [](const int& nIndex) const
{
return m_Data[nIndex];
}
main
#include "stdafx.h"
#include "myarray.h"
#include <iostream>
int main()
{
MyArray *array = new MyArray(2);
std::cout << "----------------------------" << std::endl;
std::cout << "请输入需要删除的对象:";
int m = 0;
std::cin >> m;
array->DeleteAt(m);
std::cout << "删除成功!" << std::endl;
std::cout << "打印" << std::endl;
std::cout << "--------------------------------" << std::endl;
std::cout << "请输入需要设置的新的数组大小:";
std::cin >> m;
array->SetSize(m);
std::cout << "新的数组大小为:" << array->GetSize() << std::endl;
std::cout << "----------------------------------" << std::endl;
std::cout << "请输入需要插入的值:";
std::cin >> m;
array->PushBack(m);
std::cout << "新的数组大小:" << array->GetSize() << std::endl;
std::cout << "打印" << std::endl;
std::cout << "--------------------------------" << std::endl;
std::cout << "请输入需要插入的位置,和值:";
double val = 0;
std::cin >> m >> val;
array->InsertAt(m, val);
std::cout << "打印" << std::endl;
// // array->InsertAt(8,20);
// std::cout<<"--------------------------------"<<std::endl;
// array->Print();
std::cout << "请输入需要修改的位置,和新的值:";
double value = 0;
std::cin >> m >> value;
array->SetAt(m, value);
std::cout << "新的值为:" << array->GetAt(m) << std::endl;
std::cout << "array----------------------------------" << std::endl;
array->print();
std::cout << "arr-----------------------" << std::endl;
MyArray arr;
arr.SetSize(5);
arr.InsertAt(3, 6);
arr.print();
std::cout << "array-----------------------------" << std::endl;
array->swap(arr);
array->GetAt(3);
array->print();
std::cout << "arr---------------------------------" << std::endl;
arr.print();
return 0;
}