C++类模板练习 —— 自定义数组类实现

本文最后更新于:2021年2月5日 晚上

概览:自定义数组类的实现.


C++类模板练习 —— 自定义数组类的实现

需求:

  • 可以对内置数据类型以及自定义数据类型的数据进行存储
  • 将数组中的数据存储到堆区
  • 构造函数中可以传入数组的容量
  • 提供对应的拷贝构造函数以及operator=防止浅拷贝问题
  • 提供尾插法和尾删法对数组中的数据进行增加和删除
  • 可以通过下标的方式访问数组中的元素 —— 重载[]运算符
  • 可以获取数组中当前元素个数和数组的容量

实现

  • 这些代码单独一个文件,存储于.hpp中。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
template<class T>
class MyArray {

public:
MyArray(int capacity);
~MyArray();

//拷贝构造
MyArray(const MyArray& other);

//重载=操作符
MyArray<T>& operator=(const MyArray& other);

//重载[]操作符
T& operator[](int index);

//push方法
void Push_back(const T& val);

//pop方法
void Pop_back();

//获取数组大小
int GetSize() {
return this->m_size;
}

//获取数组容量
int GetCapacity() {
return this->m_capacity;
}


private:
T *m_arr; //元素首地址
int m_size; //当前的元素个数
int m_capacity;//数组的容量
};

template<class T>
MyArray<T>::MyArray(int capacity)
{
this->m_capacity = capacity;
this->m_size = 0;
this->m_arr = new T[capacity];
}

template<class T>
MyArray<T>::~MyArray()
{
if (this->m_arr != nullptr) {
delete[]this->m_arr;
this->m_arr = nullptr;
}
}

template<class T>
MyArray<T>::MyArray(const MyArray & other)
{
//拷贝构造函数
this->m_capacity = other.m_capacity;
this->m_size = other.m_size;

//防止浅拷贝
this->m_arr = new T[this->m_capacity];

for (int i = 0; i < this->m_size; i++) {
this->m_arr[i] = other.m_arr[i];
}

//直接写other[i]会报错:
//错误二进制“[”:没有找到接受“const MyArray<int>”类型的左操作数的运算符(或没有可接受的转换)

}

template<class T>
MyArray<T>& MyArray<T>::operator=(const MyArray & other)
{
//若原来有数据,则释放掉!
if (this->m_arr != nullptr) {
delete[]this->m_arr;
this->m_arr = nullptr;
this->m_capacity = 0;
this->m_size = 0;
}

this->m_capacity = other.m_capacity;
this->m_size = other.m_size;

this->m_arr = new T[this->m_capacity];

for (int i = 0; i < this->m_size; i++) {
this->m_arr[i] = other.m_arr[i];
}

return *this;
}

template<class T>
T& MyArray<T>::operator[](int index)
{
//重载[]运算符
return this->m_arr[index];
//数组越界等问题,交给编译器和程序员
}

template<class T>
void MyArray<T>::Push_back(const T & val)
{
if (this->m_size >= this->m_capacity) {
cout << "数组容量已满" << endl;
return;
}
this->m_arr[this->m_size] = val;
this->m_size++;
}

template<class T>
void MyArray<T>::Pop_back()
{
if (this->m_size <= 0) {
return;
}
this->m_size--; //仅做逻辑删除
}
  • 值得注意的一点,对于自定义数据类型时,对于拷贝构造和重载=赋值运算符那里的this->m_arr[i] = other.m_arr[i];,若自定义数据类型有指针类型的成员,一定要重载=运算符,方式编译器自己生成的函数会有浅拷贝的问题!
  • 重载=赋值运算符,记得先释放掉原有的数据。

内置数据类型数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
void test1() {

//测试内置的数据类型
MyArray<int> int_array(10);

for (int i = 0; i < 10; i++) {
int_array.Push_back(i);
}

int size = int_array.GetSize();
for (int i = 0; i < size; i++)
cout << int_array[i] << " ";
cout << endl;

//测试拷贝构造函数

MyArray<int> int_array2(int_array);

size = int_array2.GetSize();
for (int i = 0; i < size; i++)
cout << int_array2[i] << " ";
cout << endl;

//测试 赋值操作符
MyArray<int> int_array3(1);

int_array3 = int_array2;

size = int_array3.GetSize();
for (int i = 0; i < size; i++)
cout << int_array3[i] << " ";
cout << endl;

//测试 增加与删除

int_array3.Pop_back();
int_array3.Pop_back();

int_array3.Push_back(100);

size = int_array3.GetSize();
for (int i = 0; i < size; i++)
cout << int_array3[i] << " ";
cout << endl;
}

测试自定义数据类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
class Cat {
public:
Cat() {};
Cat(string name, int age) :m_name(name), m_age(age) {}

//没有指针类型或者存放于堆区的数据,就不再实现拷贝构造 以及 重载=运算符

void showInfo() {
cout << "name: " << this->m_name << ", m_age: " << m_age << endl;
}

private:
string m_name;
int m_age;
};


void test2() {

//测试自定义数据类型
Cat c1("Bob", 2);
Cat c2("Tom", 3);
Cat c3("Jerry", 2);

//测试构造函数,插入

MyArray<Cat> cat_arr(2);

cat_arr.Push_back(c1);
cat_arr.Push_back(c2);

int size = cat_arr.GetSize();
for (int i = 0; i < size; i++)
cat_arr[i].showInfo();

//测试拷贝构造
MyArray<Cat> cat_arr2(cat_arr);

size = cat_arr2.GetSize();
for (int i = 0; i < size; i++)
cat_arr2[i].showInfo();

//测试 =
MyArray<Cat> cat_arr3(1);

cat_arr3 = cat_arr2;

cat_arr3.Pop_back();

size = cat_arr3.GetSize();
for (int i = 0; i < size; i++)
cat_arr3[i].showInfo();

}

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!