《基础知识——数组与指针、野指针》

本文详细介绍了C++中的数组创建和销毁,包括一维数组和二维数组。接着讲解了指针数组、数组指针、函数指针及其数组、野指针的概念和应用场景。特别提到了野指针的产生原因和危害,以及如何避免内存泄漏问题。最后提及了智能指针和相关内存管理策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

数组与指针的区别与联系
 

数组

指针

概念

保存数据保存数据的地址

赋值

只能一个一个元素的赋值或拷贝同类型指针变量可以相互赋值
存储方式

在内存中是连续存放

数组的存储空间,不是在静态区就是在栈上

可以指向任意类型的数据

指针的存储空间不能确定

求sizeof数组所占存储空间的内存:sizeof(数组名) 
数组的大小:sizeof(数组名)/sizeof(数据类型)
在32位平台下,无论指针的类型是什么,sizeof(指针名)都是4,在64位平台下,无论指针的类型是什么,sizeof(指针名)都是8。
初始化
(1)char a[]={"Hello"};//按字符串初始化,大小为6.
(2)char b[]={'H','e','l','l'};//按字符初始化(错误,输出时将会乱码,没有结束符)
(3)char c[]={'H','e','l','l','o','\0'};//按字符初始化

 

//(1)指向对象的指针:(()里面的值是初始化值)
int *p=new int(0) ;    delete p;
//(2)指向数组的指针:(n表示数组的大小,值不必再编译时确定,可以在运行时确定)
int *p=new int[n];    delete[] p;
//(3)指向类的指针:(若构造函数有参数,则new Class后面有参数,否则调用默认构造函数,delete调用析构函数)
Class *p=new Class;  delete p;
//(4)指针的指针:(二级指针)
int **pp=new (int*)[1]; 
pp[0]=new int[6];
delete[] pp[0];
传参数组传参时,会退化为指针。
(1)退化的意义:C语言只会以值拷贝的方式传递参数,参数传递时,如果只拷贝整个数组,效率会大大降低,并且在参数位于栈上,太大的数组拷贝将会导致栈溢出。 
(2)因此,C语言将数组的传参进行了退化。将整个数组拷贝一份传入函数时,将数组名看做常量指针,传数组首元素的地址。

1.一级指针传参

当函数参数部分是一级指针时,可以接受什么参数例如:

(1)可以是一个整形指针 
(2)可以是整型变量地址 
(3)可以是一维整型数组数组名

2.二级指针传参

即当函数参数部分是二级指针时,可以接受什么参数例如:

(1)二级指针变量 
(2)一级指针变量地址 
(3)一维指针数组的数组名

【补充】:

  • 数组的创建和销毁

(1)一维数组: 
int* arr = new int[n];//创建一维数组 
delete[] arr;//销毁 
(2)二维数组: 
int** arr = new int*[row];//这样相当于创建了数组有多少行 
for(int i=0;i<row;i++) 

arr[i] = new int[col];//到这里才算创建好了 

//释放 
for(int i=0;i<row;i++) 

delete[] arr[i]; 

delete[] arr;

  • 指针数组、数组指针

(1)指针数组:它实际上是一个数组,数组的每个元素存放的是一个指针类型的元素。

int* arr[8];
//优先级问题:[]的优先级比*高
//说明arr是一个数组,而int*是数组里面的内容
//这句话的意思就是:arr是一个含有8和int*的数组

 

(2)数组指针:它实际上是一个指针,该指针指向一个数组。

int (*arr)[8];
//由于[]的优先级比*高,因此在写数组指针的时候必须将*arr用括号括起来
//arr先和*结合,说明p是一个指针变量
//这句话的意思就是:指针arr指向一个大小为8个整型的数组。

 

  • 函数指针、函数指针数组、函数指针数组的指针

(1)函数指针

  • 定义:

函数指针是指向函数的指针变量。函数指针本身首先是一个指针变量,该指针变量指向一个具体的函数。这正如用指针变量可指向整型变量、字符型、数组一样,这里是指向函数。C在编译时,每一个函数都有一个入口地址,该入口地址就是函数指针所指向的地址。有了指向函数的指针变量后,可用该指针变量调用函数,就如同用指针变量可引用其他类型变量一样,在这些概念上是大体一致的。

  • 用途:

调用函数和做函数的参数,比如回调函数。

  • 示例:
char * fun(char * p)  {…}    // 函数fun

char * (*pf)(char * p);      // 函数指针pf

pf = fun;                    // 函数指针pf指向函数fun

pf(p);                       // 通过函数指针pf调用函数fun

函数指针的形式:类型(*)( ),例如:int (*p)( ).它可以存放函数的地址,在平时的应用中也很常见。

(2)函数指针数组

形式:例如int (*p[10])( ); 
因为p先和[ ]结合,说明p是数组,数组的内容是一个int (*)( )类型的指针 
函数指针数组在转换表中应用广泛

(3)函数指针数组的指针

指向函数指针数组的一个指针,也就是说,指针指向一个数组,数组的元素都是函数指针

void test(const char* str)
{
printf("%s\n", str);
}
int main()
{
//函数指针pfun
void (*pfun)(const char*) = test;
//函数指针的数组pfunArr
void (*pfunArr[5])(const char* str);
pfunArr[0] = test;
//指向函数指针数组pfunArr的指针ppfunArr
void (*(*ppfunArr)[10])(const char*) = &pfunArr;
return 0;
}
  • 野指针是什么?

野指针就是指向一个已删除的对象或者未申请访问受限内存区域的指针。

造成野指针的原因?分两种情况:

1. 指针变量没有被初始化;

2. 指针被delete后,未被置为NULL,让人误以为是“合法指针“。

【注意】

1. 指针置为NULL,而不delete,会造成内存泄漏

2. 将指针delete而不置为NULL,会形成“野指针”

3. delete只是把指针所指向的内存给释放掉,并没有把指针本身干掉。指针所存地址并未改变,只是该地址对应的内存已被释放,p成了“野指针”;

  • 智能指针、智能指针内存泄漏情况及解决方法

《基础知识——c++中四个智能指针》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值