前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >new和delete

new和delete

作者头像
用户7272142
发布2023-10-11 21:13:40
1650
发布2023-10-11 21:13:40
举报
文章被收录于专栏:Republic博客Republic博客

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

代码语言:javascript
复制
int *x = new int;

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

代码语言:javascript
复制
#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释放

代码语言:javascript
复制
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; 搭配规则:

不要用delete释放不是new创建的内存

不要使用delete释放一块内存两次

涉及动态数组的创建,应该用delete[]释放,如果是为实体分配内存,则需要用delete来释放。

动态数组

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

动态数组的遍历

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

代码语言:javascript
复制
#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,增加的量等于它指向类型的字节数。

代码语言:javascript
复制
#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) 因此在很多情况下,可以用相同的方式使用指针名和数组名,对于他们,可以使用数组方括号表示,也可以解引用,区别是指针可以被修改,而数组名无法修改

代码语言:javascript
复制
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的区别

代码语言:javascript
复制
 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;
本文参与?腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2023-09-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客?前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与?腾讯云自媒体分享计划? ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • delete释放内存
  • 使用new来创建动态数组
    • 动态数组
      • 动态数组的遍历
        • 指针算数
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
        http://www.vxiaotou.com