new和delete

在C语言中,我们可以通过malloc分配堆上的内存,但是C++时使用new来分配内存

int *x = new int;


上述代码为指针变量x申请了一块大小为四字节的内存,并用指针变量指向了这块内存。
注意区分将变量地址赋给指针变量的情况,如int*x = &q;第二种情况可以通过q访问这个变量内存的值,而第一种只能通过指针变量访问,格式如下:
typename * ponitername = new typename;

#include<iostream>
using namespace std;
int main()
{
	
	int* Pnights = new int;
	*Pnights = 1001;
	cout << "int"
		<< "value = " << *Pnights << " :location " << Pnights << endl;
	double* pdouble = new double;
	*pdouble = 1000000000001;
	cout << "double"
		<< "value = " << *pdouble << " :location " << pdouble << endl;
	//验证一下这几个类型的大小
	cout << "sizeof(Pnights) = " << sizeof(Pnights) << endl;
	cout << "sizeof(*Pnights) = " << sizeof(*Pnights) << endl;
	cout << "sizeof(pdouble) = " << sizeof(pdouble) << endl;
	cout << "sizeof(*pdouble) = " << sizeof(*pdouble) << endl;
}

该程序为int和double申请了内存区域,指针指向了两个内存空间用来访问这一块内存,这两个地址都是占4个字节的指针,而我们申明了申请内存空间的类型,所以我们可以知道*Pnights和*pdouble分别是4字节和8字节。

delete释放内存

我们申请完的地址,在程序退出之前是不会释放占用的,跟栈区的变量有差别,我们使用delete,可以将用完的内存还给内存池,C语言使用free而在C++中用的是delete释放

int*p = new int;
delete p;

我们这样只是释放了内存空间,指针还是存在的,可以用ps重新指向一块新的内存,如果不配对使用new和delete,会发生内存泄漏。
delete只能用来释放new出来的内存空间,但是对于空指针用delete也是安全的,但也是无意义的。

使用new来创建动态数组

我们平时要申请一个简单变量,在栈上管理内存肯定比堆上要方便,但是对于大型数据(数组 字符串和结构),用new更加合适。如果通过声明来创建数组,则程序在编译时就为数组分配了内存空间,数组一直存在,内存也一直在占用,这种分配内存的方式叫静态联编。如果new,在运行时,如果需要数组,则会创建,不需要则不创建。此外还可以选择创建数组的长度,这被成为动态联编,这种数组也被称为动态数组。静态联编必须在编写程序的时候就确定数组的长度,而动态联编,在运行时确定数组长度。
比如要创建一个10个int的数组
int * p = new int[10];
然后返回创建内存块的地址给指针变量p,对于数组的释放delete [] p;
搭配规则:

  1. 不要用delete释放不是new创建的内存
  2. 不要使用delete释放一块内存两次
  3. 涉及动态数组的创建,应该用delete[]释放,如果是为实体分配内存,则需要用delete来释放。

动态数组

type_name* poniter_name = new type_name[num_elements];
poniter_name指向了数组的第一个元素地址,同时我们也可以用数组名表示元素第一个的地址。

动态数组的遍历

跟一般数组遍历方法是一样的,需要明确的是,数组名是指针常量不能修改其指向,因此用数组名进行遍历是错误的,我们这里有一个指向数组的指针,就可以用这个指针变量来遍历这个数组。

#include<iostream>
using namespace std;
int main()
{

	double* x = new double[10];
	x[0] = 1.0;
	x[1] = 2.0;
	x[2] = 3.0;
	cout << "x[0] = " << x[0] << endl;
	x++;
	cout << "x[0] = " << x[0] << endl;
	x--;
	cout << "x[0] = " << x[0] << endl;
	delete[]x;
	return 0;
}

指针算数

指针和数组等价的原因在于指针算数和C++内部处理数组的方式。指针变量+1,增加的量等于它指向类型的字节数。

#include<iostream>
using namespace std;
int main()
{
	

	double wages[3] = { 1000.0,2000.0,3000.0 };
	short stacks[3] = { 3,2,1 };
	double* Pwages = wages;
	short* Pstacks = &stacks[0];
	cout << "Pwages = " << Pwages << " *Pwages = " << *Pwages<<endl;
	Pwages++;
	cout << "Pwages = " << Pwages << " *Pwages = " << *Pwages << endl;
	cout << "Pstacks = " << Pstacks << " *Pstacks = " << *Pstacks << endl;
	Pstacks++;
	cout << "Pstacks = " << Pstacks << " *Pstacks = " << *Pstacks << endl;
	cout << " stacks[0] = " << stacks[0] << endl;
	cout << " stacks[1] = " << stacks[0] << endl;
	cout << "*stacks = " << *stacks << ",*(stacks+1) = " << *(stacks + 1) << endl;
	cout << sizeof(wages) << " = size of wages arry" << endl;
	cout << sizeof(Pwages) << " = size of poniter Pstacks "<<endl;

}

这些内容我前面C语言笔记大部分都有,不再过度赘述。
数组名表示法
arryname[i] = *(arryname +i)
指针表示法
ponitername[i] = *(ponitername+i)
因此在很多情况下,可以用相同的方式使用指针名和数组名,对于他们,可以使用数组方括号表示,也可以解引用,区别是指针可以被修改,而数组名无法修改

short tell[10];
cout<<&tell[0];
cout<<tell;

从输出结果来看&telltell是一样的,但是概念上,&tell表示这个20字节的内存块的首地址,tell表示2字节内存块地址。tell+i表示tell地址+2,&tell+i ,则表示地址+20 tell相当于short指针 &tell相当于指向了包含10个元素的short数组
当然我们也可以用二维数组指针指向数组首地址 我们把一维的short数组看成0行但是有20列的数组集合,也就是short (*P)[10] 表示里面有,我们之前也说过二维数组,(*P)表示每个一维数组(也就是每个数组首地址)。这里也为了区分&tell和tell的区别

	short tell[10] = {1,2,3,4,5,6,7,8,9,10};
	cout << "tell = " << tell << endl;
	cout << "&tell = " << &tell << endl;
	short(*p)[10] = &tell;
	cout << "(*p)[1] = " << (*p)[2] << endl;
	short* pptell = tell;
	cout << "*(p+2) = " << *(pptell +2) << endl;

网站标题:CV鼻祖洋芋

原创文章,作者:locus,如若转载,请注明出处:https://blog.cvpotato.cn/forward-code/c/194/

本博客所发布的内容,部分为原创文章,转载注明来源,网络转载文章如有侵权请联系站长!

(0)
上一篇 6天前
下一篇 6天前

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注