C++ 手把手教你实现可变长的数组
01 实现自定义的可变长数组类型
假设我们要实现一个会自动扩展的数组,要实现什么函数呢?先从下面的main函数给出的实现,看看有什么函数是需要我们实现的。
int main()
{MyArray a; // 初始化的数组是空的for(int i = 0; i < 5; ++i)a.push_back(i); // push_back是成员函数MyArray a2,a3;a2 = a; // 重载赋值运算符函数// 由于上一句a2 = a语句,所以a.length()实际上就是a2.length()for(int i = 0; i < a.length(); ++i) cout << a2[i] << " ";a2 = a3; // a2是空的数组for(int i = 0; i < a2.length(); ++i) // a2.length()返回0cout << a2[i] << " ";cout << endl;a[3] = 100; // 重载[]运算符函数MyArray a4(a); // 重载复制构造函数for(int i = 0; i < a4.length(); ++i)cout << a4[i] << " ";return 0;
}
输出结果:
0 1 2 3 4
0 1 2 100 4
要实现的方式,要做哪些事情呢?我先列一下:
- 要用动态分配的内存来存放数组元素,需要一个指针成员变量
- 重载赋值=运算符
- 重载[]运算符
- 重载复制构造函数
- 实现push_back和length()函数
02 MyArray类的实现步骤
要实现一个可变长数组类的,基本需要实现下面的7个函数:
class MyArray // 可变长数组类
{public:// 1. 构造函数,s代表数组元素的个数MyArray(int s = 0);// 2. 复制构造函数MyArray(MyArray &a);// 3. 析构函数~MyArray();// 4. 重载赋值=运算符函数,用于数组对象间的赋值MyArray & operator=(const MyArray & a);// 5. 重载[]运算符函数,用于获取数组下标对于的值int & operator[](int i);// 6. 加入一个元素到数组的末尾void push_back(int v);// 7. 获取数组的长度int length();private:int m_size; // 数组元素的个数int* m_ptr; // 指向动态分配的数组
};
1. 构造函数
构造函数的目的就是初始化一个数组,代码如下:
// 构造函数
MyArray::MyArray(int s = 0):m_size(s)
{// 当初始化长度为0的数组时,数组指针就是空的if(s == 0)m_ptr = NULL;// 当初始化长度不为0时,则申请对应大小的空间elsem_ptr = new int[s];
}
2. 复制构造函数
复制构造函数目的就是产生一个与入参对象一样的对象,但是由于MyArray
类是有指针成员变量的,所以我们必须才用深拷贝的方式来实现复制构造函数,如果使用默认的复制构造函数,则会导致两个对象的指针成员变量指向的地址是同一个,这是非常危险的。
// 复制构造函数
MyArray::MyArray(const MyArray &a)
{// 如果入参的数组对象的指针地址为空时,则也初始化一个空的数组if(a.m_ptr == NULL){m_ptr = NULL;m_size = 0;}// 如果入参的数组对象有数据时,则申请一个新的地址,最后来复制入参对象数组对象的数据和大小。else{m_ptr = new int[a.m_size];memcpy(m_ptr, a.m_ptr, sizeof(int)*a.m_size);m_size = a.m_size;}
}
3. 析构函数
析构函数的目的就是释放数组的资源
// 析构函数
MyArray::~MyArray()
{// 如果指针地址不为空时,则释放资源if(m_ptr)delete [] m_ptr;
}
4. 重载赋值=运算符函数
重载赋值=运算符函数目的就使=
号左边对象里存放的数组,大小和内容都和右边的对象一样
// 重载赋值=运算符函数
MyArray & MyArray::operator=(const MyArray & a)
{if(m_ptr == a.m_ptr) // 防止a=a这样的赋值导致出错return *this; if(a.m_ptr == NULL) // 如果a里面的数组是空的{if(m_ptr)delete [] m_ptr; // 释放旧数组的资源m_ptr = NULL;m_size = 0;return *this;}if(m_size < a.m_size) // 如果原有空间足够大,就不用分配新的空间{if(m_ptr)delete [] m_ptr; // 释放旧数组的资源m_ptr = new int[a.m_size]; // 申请新的内存地址}memcpy(m_ptr, a.m_ptr, sizeof(int)*a.m_size);m_size = a.m_size;return *this;
}
5. 重载[]运算符函数
重载[]运算符函数目的就是能通过[]运算符来获取对应下标的数组值
// 重载[]运算符函数
int & MyArray::operator[](int i)
{return m_ptr[i]; // 返回对应下标的数组值
}
6. 加入元素到数组末尾的函数
push_back函数的目的就是把一个新的元素,加入到数组的末尾
// 在数组尾部添加一个元素
void MyArray::push_back(int v)
{if(m_ptr) // 如果数组不为空{int *tmpPtr = new int[m_size + 1]; // 重新分配空间memcpy(tmpPtr, m_ptr, sizeof(int)*m_size); // 拷贝原数组内容delect [] m_ptr;m_ptr = tmpPtr;}else // 如果数组本来就是空的{m_ptr = new int[1]; }m_ptr[m_size++] = v; //加入新的数组元素
}
7. 获取数组长度的函数
length()函数就比较简单了,直接返回成员变量m_size,就是数组的长度了
// 获取数组长度的函数
int MyArray:;length()
{return m_size;
}
03 小结
可变长数组类型实现的整体代码,如下:
class MyArray
{public:// 1. 构造函数,s代表数组元素的个数MyArray(int s = 0):m_size(s){if(s == 0)m_ptr = NULL;elsem_ptr = new int[s];}// 2. 复制构造函数MyArray(const MyArray &a){if(a.m_ptr == NULL){m_ptr = NULL;m_size = 0;}else{m_ptr = new int[a.m_size];memcpy(m_ptr, a.m_ptr, sizeof(int)*a.m_size); // 拷贝原数组内容m_size = a.m_size;}}// 3. 拷贝构造函数~MyArray(){if(m_ptr)delete [] m_ptr;}// 4. 重载赋值=运算符函数MyArray & operator=(const MyArray & a){if(m_ptr == a.m_ptr)return *this;if(a.m_ptr == NULL){if(m_ptr)delete [] m_ptr;m_ptr = NULL;m_size = 0;return *this;}if(m_size < a.m_size){if(m_ptr)delete [] m_ptr;m_ptr = new int[a.m_size];}memcpy(m_ptr, a.m_ptr, sizeof(int)*a.m_size); // 拷贝原数组内容m_size = a.m_size;return *this;}// 5. 重载[]运算符函数int & operator[](int i){return m_ptr[i];}// 6. 在数组的末尾加入一个新的元素void push_back(int v){if(m_ptr) // 如果数组不为空{int *tmpPtr = new int[m_size + 1]; // 重新分配空间memcpy(tmpPtr, m_ptr, sizeof(int)*m_size); // 拷贝原数组内容delete [] m_ptr;m_ptr = tmpPtr;}else // 如果数组本来就是空的{m_ptr = new int[1]; }m_ptr[m_size++] = v; //加入新的数组元素}// 7. 获取数组的长度int length(){return m_size;}private:int m_size; // 数组元素的个数int* m_ptr; // 指向动态分配的数组
};
实际上本次的可变长的数组类还缺少一下函数,比如:删除某个元素的函数、清空数组的函数等等,这些可以留给大家思考。
还有就是 push_back 函数还有优化的空间,当前的 push_back 函数每加入一个元素都会重新分配新的内存,这是会增大开销的,那么优化的思路:
提前分配好一个 n 大小的空间,当数组大小不够的时候,则才继续重新分配 2n 大小的空间,以此类推。
C++ 手把手教你实现可变长的数组相关推荐
- C/C++编程知识分享:C++ 手把手教你实现可变长的数组
01 实现自定义的可变长数组类型 假设我们要实现一个会自动扩展的数组,要实现什么函数呢?先从下面的main函数给出的实现,看看有什么函数是需要我们实现的. 输出结果: 要实现的方式,要做哪些事情呢?我 ...
- delphi 获取数组长度_C++可变长的数组,老司机手把手教你实现!
01 实现自定义的可变长数组类型 假设我们要实现一个会自动扩展的数组,要实现什么函数呢?先从下面的main函数给出的实现,看看有什么函数是需要我们实现的. int main(){ MyArray a; ...
- socket 长链接linux,手把手教你写 Socket 长连接
原标题:手把手教你写 Socket 长连接 8点43分打卡 就是真爱 本文转载自公众号 玉刚说,由玉刚说写作平台[1]提供写作赞助 原作者:水晶虾饺[2] 版权声明:本文版权归微信公众号玉刚说所有,未 ...
- 手把手教你写 Socket 长连接
本文由玉刚说写作平台[1]提供写作赞助 原作者:水晶虾饺[2] 版权声明:本文版权归微信公众号 玉刚说 所有,未经许可,不得以任何形式转载 本篇我们先简单了解一下 TCP/IP,然后通过实现一个 ec ...
- 怎样在数组末尾添加数据_如何利用C++实现可变长的数组?
应该执行什么功能? 假设我们要实现一个将自动扩展的数组类,是否需要实现函数?让我们从下面主要功能使用的功能开始,看看我们需要实现哪些功能. 输出结果: 0 1 2 3 4 0 1 2 100 4 您需 ...
- C++可变长数组vector的使用
最近在刷算法,C++里自带的一些容器.函数真是非常简便了. 下面介绍一种可变长的数组,和数组类似,但比数组更强大更方便~~~ 可边长数组: vector<int> v(N,i); 头文件: ...
- 高效 保活长连接:手把手教你实现 自适应的心跳保活机制
前言 当实现具备实时性需求时,我们一般会选择长连接的通信方式 而在实现长连接方式时,存在很多性能问题,如 长连接保活 今天,我将 手把手教大家实现自适应的心跳保活机制,从而能高效维持长连接 目录 1. ...
- 其他行 展开 收起_长居清迈的家庭,去台湾依旧可以自由行?手把手教你网上申请赴台证...
台北@西门町 8月份有朋友告诉我们,在大陆叫停台湾自由行之后,持泰国长居签证的大陆居民,依旧可以向曼谷的驻泰国台北经济文化办事处申请台湾自由行,而且全程只需要在网上提交资料+缴费+下载许可证,高兴坏了 ...
- android 心跳 简书,如何高效维持网络长连接:手把手教你实现 自适应的心跳保活机制...
前言 当实现具备实时性需求时,我们一般会选择长连接的通信方式 而在实现长连接方式时,存在很多性能问题,如 长连接保活 今天,我将 手把手教大家实现自适应的心跳保活机制,从而能高效维持长连接 目录 示意 ...
最新文章
- 中国大学的现实:层次越低,上课越多,学生读书越少
- 沈向洋官宣离职微软!他是微软级别最高的中国人、微软AI领导者,21年前参与创办MSRA...
- 零基础可以学python吗-python零基础能学吗
- php 7.1/7.3使用 json_encode 函数造成浮点类型数据出现精度问题
- Redis源码剖析(二)io多路复用函数及事件驱动流程
- celery学习笔记:celery安装,并运行第一个应用
- 家乐福举报山姆涉嫌“二选一”背后 会员店需要的不是模仿能力
- python如何调用阿里云接口_Python调用阿里云API接口实现自定义功能【二】——DescribeInstance窗口操作...
- 火狐与IE兼容性总结(一)
- 【信息技术】【2014】【含源码】PGP加密软件
- 夜神模拟器安装frida-server图文详解
- python时间序列进行线性插值_精解Python实现线性插值法——一看就会
- 科学计算机算方差与期望,期望、方差、协方差及相关系数的基本运算
- 阅读心得:JDE:Towards Real-Time Multi-Object Tracking
- 干货 领导力21法则思考
- python re span_python—模块-re正则表达式
- Mac sublime3 在localhsot 上打开项目文件
- 数据库课程设计----学生信息与选课、成绩评价管理系统
- 苹果电脑查看已经连上的WiFi密码(亲测可用)
- 51单片机入门——Proteus 8 Professional的使用
热门文章
- Loose Ends
- 修复电脑蓝屏(电脑自动修复失败)
- python3--最新google_trans_new超时报错JSONDecodeError解决
- 东北计算机考研难度性价比,全国211院校考研难度分析,建议收藏!(详细版)...
- 微信支付上线遇到的nss问题 (openjdk引起的祸)
- https://nbicddnbp.pxvqgzr.com/f/Y315nOiv1 fu指喲 考貝该段,点開块手
- 网络系统管理Debian模块||RouterSrv的openvpn配置详解
- Matrix矩阵的基础案例与分析
- MATLAB信号处理——分解信号,双谱重构
- 【劳动最光荣】TcaplusDB祝大家劳动节快乐