C++ 一个有关类模板、构造函数、析构函数、拷贝构造、重载等的数组案例分析

概要

案例描述: 实现一个通用的数组类,要求如下:

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

根据代码和输出进行分析(看注释和图示)

MyArray.hpp代码:

#pragma once
#include<iostream>
using namespace std;


template<class T>
class MyArray
{
public:
    //有参构造 参数 容量
    MyArray(int capacity)
    {   
        cout << "MyArray的有参构造调用" << endl;
        this->m_Capacity = capacity; // 期望所存
        this->m_Size = 0; //现存
        this->pAddress = new T[this->m_Capacity];
    }

    //拷贝构造函数 防止浅拷贝问题
    MyArray(const MyArray& arr)
    {   
        cout << "MyArray的拷贝构造调用" << endl;
        this->m_Capacity = arr.m_Capacity;
        this->m_Size = arr.m_Size;
        // this->pAddress = arr.pAddress; //默认拷贝构造函数会这么写,造成堆区数据重复释放

        //深拷贝
        this->pAddress = new T[arr.m_Capacity];
        //将arr中的数据都拷贝过来
        for (int i = 0; i < this->m_Size; i++)
        {   
            // 如果T为对象,而且还包含指针,必须需要重载 = 操作符,因为这个等号不是 构造 而是赋值,
			// 普通类型可以直接= 但是指针类型需要深拷贝
            this->pAddress[i] = arr.pAddress[i];
        }
    }

    //operator= 防止浅拷贝问题  a=b=c 自带的=能实现链式编程
    MyArray& operator=(const MyArray& arr)
    {   
        cout << "MyArray的operator=赋值运算符重载调用" << endl;
        //先判断原来堆区是否有数据,如果有先释放
        if (this->pAddress != nullptr){
            delete [] this->pAddress;
            this->pAddress = nullptr;
            this->m_Capacity = 0;
            this->m_Size = 0;
        }

        //深拷贝
        this->m_Capacity = arr.m_Capacity;
        this->m_Size = arr.m_Size;
        this->pAddress = new T[arr.m_Capacity];
        for (int i = 0; i < this->m_Capacity; i++){
            this->pAddress[i] = arr.pAddress[i];
        }
        
        return *this; //MyArray& = *this
    }

    //尾插法
    void Push_Back(const T & val){
        //判断容量是否等于大小
        if (this->m_Capacity == this->m_Size){
            return;
        }
        this->pAddress[this->m_Size] = val;
        this->m_Size++;
    }

    //尾删法
    void Pop_Back(){
        //让用户访问不到最后一个元素,即为尾删(逻辑上的删除方式)
        if (this->m_Size == 0){
            return;
        }
        this->m_Size--;
    }

    //让用户通过下标方式访问数组中的元素
    //重载[],因为数据类型是我们自己定义的
    T& operator[] (int index){ //arr[0] = 100 为了让它可以做左值,需要返回T的引用  这种思想也是链式编程思想

        return this->pAddress[index];
    }

    //返回数组容量
    int getCapacity(){
        return this->m_Capacity;
    }
    //返回数组大小
    int getSize(){
        return this->m_Size;
    }
    
    //析构函数
    ~MyArray()
    {   
        cout << "MyArray的析构函数调用" << endl;
        if(this->pAddress != nullptr){
            delete [] this->pAddress; //指向的是数组
            this->pAddress = nullptr; //指针置空,防止野指针
        }
    }

private:
    T * pAddress;

    int m_Capacity;

    int m_Size;


};

Main.cpp代码

#include <iostream>
#include "MyArray.hpp"
#include <windows.h>//用于函数SetConsoleOutputCP(65001);更改cmd编码为utf8
#include <string>
using namespace std;

void PrintIntArray(MyArray<int> arr) //会调用拷贝构造函数,如果写成MyArray<int> &arr就不会调用了!
{
    for (int i =0; i < arr.getSize(); i++){
        cout << arr[i] << endl;
    }
}

//测试内置数据类型
void test01(){
    MyArray<int> arr1(5); //有参构造  数据放在栈上
    
    for (int i = 0; i < 5; i++){
        arr1.Push_Back(i); // 尾插法
    }
    cout << "arr1的打印输出:" << endl;
    PrintIntArray(arr1);

    cout << "arr1的容量:" << arr1.getCapacity() << endl;
    cout << "arr1的大小:" << arr1.getSize() << endl;

    MyArray<int>arr2(arr1);//拷贝构造
    cout << "arr2的打印输出:" << endl;
    PrintIntArray(arr2);

    //尾删
    arr2.Pop_Back();
    cout << "arr2尾删后:" << endl;
    cout << "arr2的容量:" << arr2.getCapacity() << endl;
    cout << "arr2的大小:" << arr2.getSize() << endl;

	MyArray<int>arr3(100); //有参构造
    arr3 = arr1; //等号赋值

}

int main(){

    SetConsoleOutputCP(65001);

    test01();

    cout <<"执行完毕" <<endl;
    system("pause");

    return 0;
}

输出与解释:
在这里插入图片描述
我有个点不太确定,请大佬指正是否正确:因为arr1 2 3是创建在栈上的局部变量,所以遵循先进后出的原则释放,所以先释放arr3,然后依次释放arr2、arr1。

个人小结

上面这个案例很好的总结了C++有关类和函数的相关核心知识,获益匪浅。

花了两个多星期,黑马的课程终于看到STL模板库了,后面继续学习加油吧(ง •_•)ง

  • 8
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值