IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++:长度可变的整型数组类 -> 正文阅读

[C++知识库]C++:长度可变的整型数组类

?这个是按照北京大学郭老师c++程序设计所作的课堂笔记。

/*动态可变长数组(运算符重载)的使用
*/


#include<iostream>
using namespace std;
class CArray {
	int size;							//数组元素的个数,(有一个length成员函数,能输出数组的长度)
	int* ptr;							//指向动态分配的数组
public:
	CArray(int s = 0);					//构造函数,s代表数组元素的个数
	CArray(CArray& a);					//
	~CArray();
	void push_back(int v);				//在数组尾部添加一个元素v
	CArray& operator=(const CArray& a);	//用于数组对象间的赋值
	int length() { return size; }		//返回数组元素个数
	/*
	下面函数的作用:
	用以支持根据下标访问数组元素,如n=a[i]和a[i]=4这样的语句,
	a[]a里面的数组元素在ptr指向的动态分配的空间中。
	下面这个函数的类型是什么???
	[]是双目运算符(一个在里面,一个在外面)只有一个参数,在成员函数中,数组的下标,在这个成员函数中运用

	*/
	int& operator[](int i) {			//返回值的类型为什么是int的引用,为甚么int不行???
										//用n=a[]可以,但是用a[]=4就是不可以了
										//如果一个函数的返回值不是引用的话就不能作为=(赋值运算符)的左值、
										//同时****希望能修改a[]的值,如果是一个数值则不会修改数值,只有是ptr[]的引用才能让a[]被修改
		return ptr[i];					//返回一个数值,a[]的数值
	}
};
CArray::CArray(int s) :size(s) {		//构造函数,就已经包含多少元素//size()初始化列表
	if (s == 0)
		ptr = NULL;
	else
		ptr = new int[s];
}
CArray::CArray(CArray& a) {				//复制构造函数,深拷贝	
	if(!a.ptr) {						//主要用来判断如果指针是空指针的时候,
										//进行出错处理和return 出去。说明有错误了。
		ptr = NULL;
		size = 0;
		return;							//return出去
	}
	ptr = new int[a.size];				
	memcpy(ptr, a.ptr, sizeof(int) * a.size);//将a.ptr中的内容复制到ptr中去,并且需要有多少字节的内容,sizeof(int)*a.size
	size = a.size;							
}
CArray::~CArray() {							//释放空间
	if (ptr)delete[]ptr;					//判断是不是空指针,如果不是空指针就释放
}
CArray& CArray::operator=(const CArray& a) {//赋值号的作用是使“=”左边对象里存放的数组,大小和内容都和右边的一样
											//返回值是carray的引用,是为了符合赋值号使用的惯例,在c++中赋值表达式的返回值本来就是赋值号左面的变量的引用,
											//我们遵循这样的习惯,所以赋值号重载后的返回值仍然是CArray的引用
											//如果不是这样的话那么在c++中左值并不是一个引用,而是一个返回的值,那么这个变量就不能作为一个赋值运算符的左值
	if (ptr == a.ptr)						//防止a=a这样的赋值导致出错(特判)
		return *this;						//跳出函数
	if(a.ptr == NULL) {						//引用值的数组
		if (ptr) delete[]ptr;				//ptr中的数组内容
		ptr = NULL;
		size = 0;
		return *this;
	}
	if (size < a.size) {
		if (ptr)
			delete[]ptr;
		ptr = new int[a.size];
	}
	memcpy(ptr, a.ptr, sizeof(int) * a.size);	//其实这句话就执行了size>a.size,因为执行完上一个if语句后就来执行这个语句,
												//并且最后一种情况和if(处理size<a.size)之后需要处理的是一样的东西,所以只需要写一个就行
	size = a.size;
	return*this;
}
void CArray::push_back(int v) {				//这个比较低效应该先用比较长的存储空间(32),若不够再+32
	if (ptr) {								//在尾部加一个新的元素
		int* temPtr = new int[size + 1];	//重新分配空间
		memcpy(temPtr, ptr, sizeof(int) * size);//拷贝元素组内容
		ptr = temPtr;
	}
	else//数组本来是空的
		ptr = new int[1];
	ptr[size++] = v;//加入新的数组元素
}
/*1.要用动态分配内存来存放数组,需要一个指针成员变量
2.动态分配的内存要释放,则需要一个析构函数
3.a2=a,则需要一个重载运算符=函数
4.a2[]成立则需要一个重载[]函数,因为a2是一个类
5.CArray a4(a)则需要一个复制构造函数,并且是深复制,如果是浅复制则动态分配的空间会出错
*/
int main() {									//要编写的可变长数组,使之能如下使用
	CArray a;									//开始的数组是空的
	for (int i = 0; i < 5; ++i)
		a.push_back(i);                         //把五个整数加到数组里,有五个元素了
	CArray a2, a3;
	a2 = a;										//a2是一个新的数组a的内容和a2的内容是一样的,只是存储空间不一样
												//相互分开,此时用重载=运算符
	for (int i = 0; i < a.length(); ++i)		//打印a2,循环输出
		cout << a2[i] << " ";
	a2 = a3;									//把a3复制给a2,但是此时a3是空的所以a2需要释放掉
	for (int i = 0; i < a2.length(); ++i)		//a2没有任何输出因为此时a2是一个空数组了,a2里面没有元素
		cout << a2[i] << "";
	cout << endl;
	a[3] = 100;                                 //赋值100
	CArray a4(a);								//复制构造函数
	for (int i = 0; i < a4.length(); ++i)		
		cout << a4[i] << " ";					//0 1 2 100 4
	cout << endl;
	int c[6] = { 0 };
	CArray b;
	for (int i = 0; i < 8; i++)
		b.push_back(i);
	b = a;
	for (int i = 0; i < b.length(); i++)
		cout << b[i]<<" ";
	cout << endl;
	return 0;									
}

C++圣经《C++程序设计语言 特别版》(C++之父的著作)中说:
,C++之父认为 ,判断指针是否为空,用(p==NULL)或(p!=NULL)的格式 ?,这样写是不好的,提倡直接写(p)或(!p)的形式。 在win32开发中,if ( NULL == p )是极好的写法。但不要写成:if ( p == NULL )。
用if判断ptr是否为空指针的例子:
int* ptr;?? ??? ??? ??? ??? ??? ?//ptr是一个指针
if(!a.ptr) {?? ??? ??? ??? ??? ??? ?//主要用来判断如果指针是空指针的时候,
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?//进行出错处理和return 出去。说明有错误了。
?? ??? ?ptr = NULL;
?? ??? ?size = 0;
?? ??? ?return;?? ??? ??? ??? ??? ??? ??? ?//return出去
?? ?}
*******************************************************************************
!逻辑非运算符,用来逆转操作数的状态,使真变假,使假变真?
例如: ?!ptr(ptr是一个指针),如果ptr=NULL,则该表达式为真;
*******************************************************************************
int *P=NULL;//这里的NULL指的是指针指向的地址没有数值;
*******************************************************************************
赋值表达式:
左值:表达式可以引用到一个对象,并且这个对象是一块内存空间并可以检测和存储,这个表示即是左值。
右值:直接引用了一个存储在内存地址中的数据。
左值是一个对象或变量,代表一个固定地址,而没有固定地址的临时对象或临时变量既是右值,不能代表一个固定地址
?

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-10-16 19:28:07  更:2021-10-16 19:30:35 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 3:30:31-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码