题目描述
Rainy Memory 嫌弃 C++ 的数组很久了:不仅不会检查下标越界,也没有数组拼接、数组输出等方便的功能。学习了 OOP 知识的你,可不可以写一个类帮他解决这个问题呢?
你需要完成一个模板类 ArrayList
,有且仅有一个模板参数 T
,为数组中元素的类型。
这个类需要支持以下功能:
- 构造函数
- 从已有的数组构造:参数
T* arr, int length
,length
为arr
的长度 - 构造一个固定长度的数组:参数
int length
,其中的元素应调用其默认构造函数 - 拷贝构造函数(深拷贝,需要复制元素的值)
- 从已有的数组构造:参数
- 析构函数
- 成员函数
size()
,返回数组大小。 operator[]
的重载,支持通过[]
赋值与得到数组元素(需要同时完成左值与右值的重载)。operator+
的重载,拼接两个数组,原来的两个数组不应该改变。operator=
的重载,将本数组赋值为另一个数组,需要支持连续赋值。(同拷贝构造函数一样是深拷贝)operator==, !=
的重载,数组相同的判定条件是长度与对应位元素均相等。operator<<
的重载,格式为使用一个空格隔开数组中的所有元素,不输出换行符。- 在评测时,程序的任何输出都将通过调用
printList
函数来实现(见下方代码,略去了模板相关的内容)。因此,如果你没有完成operator<<
的重载,你也可以利用给定的print
函数并注释掉#define USE_OS
以使得评测能够正常进行,否则可能产生编译错误。print
函数同样按照格式输出到cout,不输出换行符。
- 在评测时,程序的任何输出都将通过调用
题面补充:如果你要测试 operator<<
的重载,需要在你提交的代码开头加上 #define USE_OS
void printList(ArrayList list) {
#ifdef USE_OS
std::cout << list << "\n";
#else
list.print();
std::cout << "\n";
#endif
}
保证模板参数 T
有默认构造函数,支持 operator==, <<, =
。
同时需要在出现问题时抛出异常。我们提供以下异常类:
class error : public std::exception {
private:
std::string msg;
public:
explicit error(const char *_msg_) : msg(_msg_) {}
const char *toString() {
return msg.c_str();
}
};
可能出现的异常有:
- 下标越界:下标为
0-based
,若下标越界抛出index out of bound
- 初始化长度非法:若构造函数中
length < 0
,抛出invalid length
调用示例
#include "ArrayList.hpp"
...
try {
ArrayList<char> list_err(-1);
} catch (error &e) {
std::cout << e.toString() << std::endl;
}
ArrayList<int> list(5);
try {
list[-1];
} catch (error &e) {
std::cout << e.toString() << std::endl;
}
try {
list[2000];
} catch (error &e) {
std::cout << e.toString() << std::endl;
}
for (int i = 0; i < list.size(); i++) list[i] = i;
printList(list);
ArrayList<int> temp = list;
printList(temp);
temp = list;
printList(temp);
if (temp == list) std::cout << "true" << std::endl;
int arr[5] = {4, 215, 12, 84, 76};
const ArrayList<int> list_const(arr, 5);
std::cout << list_const[3] << std::endl;
printList(list_const);
printList(list_const + list);
return 0;
...
样例输出
invalid length
index out of bound
index out of bound
0 1 2 3 4
0 1 2 3 4
0 1 2 3 4
true
84
4 215 12 84 76
4 215 12 84 76 0 1 2 3 4
输入格式
你不需要处理输入,可以参考上述调用示例。
输出格式
你不需要处理输出,可以参考上述调用示例。
数据范围
check point | 数据特征 |
---|---|
1 | 同调用样例 |
2 | 仅检测异常处理 |
3 | 鲁棒性 |
4 | 主要考察+,size |
5 | 流输出运算符重载 |
6 | 元素默认构造函数的调用 |
7 ~ 12 | 内容同上述1 ~ 6,检查内存泄漏,共20分 |
时空磁盘限制(运行时)
时间限制: 3000 ms
内存空间限制: 244 MiB
磁盘空间限制: 无限制
题目解答:
如果多次throw会导致Memory Leak 蛮难找的提交了七八次才凑出来
以及鲁棒性方面 =重载考虑自身不然delete自己再new会导致赋值不对WA
#include<iostream>
#include<cstdio>
#define USE_OS
using namespace std;
class error : public std::exception {
private:
std::string msg;
public:
explicit error(const char *_msg_) : msg(_msg_) {}
const char *toString() {
return msg.c_str();
}
};
template<typename T>
class ArrayList
{
public:
T *data;
int length;
ArrayList(T *arr, int len)
{
if (len<0) throw error("invalid length");
length=len;
data=new T[length];
int i;
for (i=0;i<length;i++)
data[i]=arr[i];
}
ArrayList(int len)
{
if (len<0) throw error("invalid length");
length=len;
data=new T[length];
}
ArrayList(const ArrayList &b)
{
if (b.length<0) throw error("invalid length");
length=b.length;
data=new T[length];
int i;
for (i=0;i<length;i++)
data[i]=b.data[i];
}
~ArrayList()
{
length=0;
delete []data;
}
int size()
{
if (length<0) throw error("invalid length");
return this->length;
}
const T &operator[](int index) const
{
if (index>=this->length || index<0) throw error("index out of bound");
return this->data[index];
}
T &operator[](int index)
{
if (index>=this->length || index<0) throw error("index out of bound");
return this->data[index];
}
bool operator==(const ArrayList &b)
{
if (!(b.length==this->length)) return false;
int i;
for (i=0;i<this->length;i++)
if (!(this->data[i]==b.data[i])) return false;
return true;
}
bool operator!=(const ArrayList &b)
{
if (!(b.length==this->length)) return true;
int i;
for (i=0;i<this->length;i++)
if (!(this->data[i]==b.data[i])) return true;
return false;
}
ArrayList &operator=(const ArrayList &a)
{
int i;
if (*this==a) return *this;
delete []data;
length=a.length;
data=new T[a.length];
for (i=0;i<a.length;i++) this->data[i]=a.data[i];
return *this;
}
};
template<typename T>
ArrayList<T> operator+(const ArrayList<T> &a,const ArrayList<T> &b)
{
ArrayList<T> t(a.length+b.length);
int i;
for (i=0;i<a.length;i++) t.data[i]=a.data[i];
for (i=a.length;i<a.length+b.length;i++) t.data[i]=b.data[i-a.length];
return t;
}
template<typename T>
ostream &operator <<(ostream &os, const ArrayList<T> &obj)
{
int i;
for (i=0;i<obj.length;i++) os<<obj.data[i]<<' ';
return os;
}