c++基础学习之动态数组

最近新到公司,带教老师让我写动态数组,哇,给我的感觉真的是,底层的东西,要求性能和代码规范比较严,下面是代码。

我会写很详细的注释,方便以后自己观看。希望各位请教了。

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;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

搁浅的渔

创作不易,多多支持

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值