服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C/C++ - C++类模板实战之vector容器的实现

C++类模板实战之vector容器的实现

2023-02-17 14:41叶落秋白 C/C++

本文我们将做一个类模板实战-手写精简版vector容器。让我们自己封装一个数组类,可以适应基本数据类型和自定义数据类型,感兴趣的可以了解一下

案例要求

可以对内置数据类型以及自定义数据类型的数据进行存储

将数组中的数据存储到堆区

构造函数中可以传入数组的容量

提供对应的拷贝构造函数以及operator=防止浅拷贝问题

提供尾插法和尾删法对数组中的数据进行增加和删除

可以通过下标的方式访问数组中的元素

可以获取数组中当前元素个数和数组的容量

完成步骤

1、封装数组类属性并完成有参构造以及析构函数

?
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
#pragma once
#include<iostream>
using namespace std;
template<class T>
class Arrays
{
private:
    T* arr;//数组arr存放T类型的数据
    int capacity;//数组容量
    int size;//数组大小
public:
    Arrays(int capacity)
    {
        this->capacity = capacity;
        this->size = 0;
        this->arr = new T[this->capacity];
    }
    ~Arrays()
    {
        if (this->arr != NULL)
        {
            delete []this->arr;
            this->arr = NULL;
        }
    }
};

我把自己的这个数组类模板放到一个.hpp文件里,方便测试的时候调用。代码第一行是为了防止头文件重复包含,template里面的T就是数组的数据类型,根据调用时不同的指定存放不同类型的数据。将数组arr以及数组容量和大小进行封装,写在私有权限下即可 。然后提供该类的有参构造,参数列表传入的是数组容量,有参构造初始化了数组的容量以及大小并将数组开辟到了堆区。析构函数就是来清理堆区数据,如果我们开辟的堆区数组不为空,那就清理掉并将其指向NULL,这样可以防止野指针出现,避免异常。

2、提供对应的深拷贝构造函数防止调用析构时出错

?
1
2
3
4
5
6
7
8
9
10
Arrays(const Arrays& p)
{
    this->capacity = p.capacity;
    this->size = p.size;
    this->arr = new T[p.capacity];
    for (int i = 0; i < this->size; i++)
    {
        this->arr[i] = p.arr[i];
    }
}

如果不提供深拷贝,那么编译器就会有:this->arr=p->arr 这行代码 ,那么一旦我们调用编译器提供的浅拷贝,当运行到析构函数时,就会出现重复删除地址的情况,必然会出现程序错误。所以我们要自己提供深拷贝构造函数,将上面的代码改为 this->arr= new T[p.capacity] ,这样调用析构的时候各自删除各的堆区数据,不会出现上述情况。最后利用for循环将传进来的对象的数据赋值给新开辟的数组。

3、重载类内的赋值运算符防止浅拷贝问题出现

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Arrays& operator=(const Arrays& p)
{
    if (this->arr!=NULL)
    {
        delete []this->arr;
        this->arr = NULL;
        this->capacity = 0;
        this->size = 0;
    }
    //深拷贝过程
    this->capacity = p.capacity;
    this->size = p.size;
    this->arr = new T[this->capacity];
    for (int i = 0; i < p.size; i++)
    {
        this->arr[i] = p.arr[i];
    }
    return *this;
}

当数组数据是对象的类型时,不能简单的将数组进行赋值操作,因为也牵扯到直接赋值出现一样的数组地址的情况,存在着深浅拷贝问题。赋值的时候是将传入参数的数据赋值给自己,因此先把自己的属性清空,然后就是深拷贝的实现了。最后返回的是*this,this指针能够指向不同成员属性,那么*this就是对象本身,然后看到返回值类型是对象引用,这样就可以实现对象间的连续赋值了。

4、提供尾部插入和删除的方法

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void insert_Arrays(const T&value)
{
    if (this->capacity == this->size)
    {
        return;
    }
    this->arr[size] = value;
    this->size++;
}
void delete_Arrays()
{
    if (this->size == 0)
    {
        return;
    }
    this->size--;
}

尾插过程:先判断数组是否已经满了,如果不满就将形参赋值给当前数组最后一个下标的位置,然后更新数组下标,这样就能保证每次插入的数据都在数组末尾。 

尾删的实现:先判断数组是否为空,不为空的时候直接把数组大小减一即可,让编译器访问不到当前的最后一个数组元素。注意尾删的只是数据的指针,数组的地址并未删除。

5、重载[]得到数组中对应下标的数据信息

?
1
2
3
4
T& operator[](int index)
{
    return this->arr[index];
}

如果数组内容是对象类型,是不存在对象数组的,所以要对[]运算符进行重载。返回值类型为数据类型的引用,也就是具体的数组内的值,传进去的整型参数就是数组下标。

6、提供get方法获取当前数组容量及大小

?
1
2
3
4
5
6
7
8
int getSize()
{
    return this->size;
}
int getCapacity()
{
    return this->capacity;
}

这里就是经典的get方法了,返回对应封装的成员属性 ,不做多解释。

7、提供打印函数测试基本数据类型和自定义数据类型的存储

?
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
#include"arrays.hpp"
class Hero
{
    friend void printHero(Arrays<Hero>&hero);
private:
    string name;
    string position;
public:
    Hero() {}
    Hero(string name, string position)
    {
        this->name = name;
        this->position = position;
    }
};
void printArrays(Arrays<int>arr)
{
    for (int i = 0; i < arr.getSize(); i++)
    {
        cout << arr[i] << " ";
    }
    cout << endl;
}
void printHero(Arrays<Hero>&hero)
{
    for (int i = 0; i < hero.getSize(); i++)
    {
        cout << "姓名:"<<hero[i].name<<" 位置:"<<hero[i].position<<endl;
    }
}
void test()
{
    cout << "普通类型数组测试:" << endl;
    cout << "输入数组容量为:" ;
    int n = 0; cin >> n;
    Arrays<int> array(n);
    cout << "输入数据:";
    for (int i = 0; i < array.getCapacity(); i++)
    {
        int value = 0;
        cin >> value;
        array.insert_Arrays(value);
    }
    cout << "打印数组信息:"<<endl;
    printArrays(array);
    array.delete_Arrays();
    cout << "删除一次尾部数据后打印数组信息:" << endl;
    printArrays(array);
}
void test1()
{
    cout << "自定义类型数组测试:" << endl;
    Hero h1("火舞","中单");
    Hero h2("韩信","打野");
    Hero h3("桑启","游走");
    Hero h4("守约","发育");
    Hero h5("关羽","对抗");
    Arrays<Hero> array(5);
    array.insert_Arrays(h1);
    array.insert_Arrays(h2);
    array.insert_Arrays(h3);
    array.insert_Arrays(h4);
    array.insert_Arrays(h5);
    printHero(array);
    array.delete_Arrays();
    cout << "删除一次尾部数据后打印数组信息:"<<endl;
    printHero(array);
}

首先引入之前封装的数组类头文件,提供printArrays和printHero函数来进行数组信息的打印,test和test1函数分别是整型数组和对象数组的测试。接下来看运行效果。

运行效果:

C++类模板实战之vector容器的实现

到此这篇关于C++类模板实战之vector容器的实现的文章就介绍到这了,更多相关C++ vector容器内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://blog.csdn.net/m0_58618795/article/details/125592238

延伸 · 阅读

精彩推荐
  • C/C++C语言线性表中顺序表超详细理解

    C语言线性表中顺序表超详细理解

    程序中经常需要将一组数据元素作为整体管理和使用,需要创建这种元素组,用变量记录它们,传进传出函数等。一组数据中包含的元素个数可能发生变化...

    李逢溪8412022-11-01
  • C/C++深入理解c语言数组

    深入理解c语言数组

    这篇文章主要介绍了c语言数组,有需要的朋友可以参考一下...

    C语言教程网8092021-01-11
  • C/C++C++中的常对象与常对象成员详解

    C++中的常对象与常对象成员详解

    常成员函数可以访问常对象中的数据成员,但仍然不允许修改常对象中数据成员的值。有时在编程时有要求,一定要修改常对象成员中的某个数据成员的值...

    C++教程网6242021-01-07
  • C/C++《C++ primer plus》读书笔记(一)

    《C++ primer plus》读书笔记(一)

    本读书笔记是C++ primer plus(第六版)前3章的学习笔记。非常的浅显易懂,复习C++基础知识的可以瞄瞄。...

    钱书康6832021-02-07
  • C/C++C++中rapidjson组装继续简化的方法

    C++中rapidjson组装继续简化的方法

    今天小编就为大家分享一篇关于C++中rapidjson组装继续简化的方法,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小...

    stpeace11552021-07-27
  • C/C++C++/GoLang如何实现自底向上的归并排序

    C++/GoLang如何实现自底向上的归并排序

    这篇文章主要给大家介绍了关于C++/GoLang如何实现自底向上的归并排序的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参...

    NothingLeft了11082021-09-26
  • C/C++C语言之实现栈的基础创建

    C语言之实现栈的基础创建

    这篇文章主要介绍了C语言之实现栈的基础创建,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下...

    小尹同学⁣10912021-12-07
  • C/C++C语言实现经典24点纸牌益智游戏

    C语言实现经典24点纸牌益智游戏

    这篇文章主要为大家详细介绍了C语言实现经典24点纸牌益智游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    Damao979392021-08-04