20.11.21对指针的学习
作者:互联网
这个礼拜都在刷学校的oj啊,,不过基本都是刷熟练度,随笔这东西我还是随性写吧,什么定时总结我还是不适合,不过偶尔的大总结还是可以有的,唉,我这个糟糕的惰性
指针:间接访问
1、指针的概念
1.1、间接访问和直接访问
指针就是地址。
定义一个变量 x ,直接使用这个变量的方式称直接访问,通过指针(地址)间接使用 x 的方式称为间接访问。
1.2、指针变量的定义
定义方式如下
int *p; //int 表示指针 p 保存的地址中储存的是个整型数.
int *p,*q; //定义两个指针变量 p,q.
int *p,q; //定义一个指针变量 p 和整型变量 q.
其中,p 才是指针变量,而 *p 是定义的格式,也是后续用来实现间接访问的形式。
指针 p 中储存的是地址,但 p 本身也有自己的地址。
1.2、指针的基操
1.2.1赋值
赋值方法:①直接将某变量的地址付给指针:
int x,*p;
p=&x; //&是取地址符
//或者
int x,*p=&x; //x 要在 p 前定义
②将同类指针变量的值直接赋给另一指针变量,如:
int x,*p=&x,*q=p;
//或者
int x,*p=&x;
int *q;
q=p;
若不赋初值:
若定义为全局,则指针 p 的值为 0 。
若定义为局部,则为随机值,所以可以给他先赋值符号常量NULL,其值为0,来表示这个指针不指向任何地址。
如:
int *q=NULL;
③不同类型指针间不能赋值
1.2.2指针变量的访问
在定义并赋予初值后,可以通过 p 来取用指针 p 中保存的地址所储存的变量。
运算符是 取指针 指向 的 值 的运算符。
int x,y,*p;
x=3;y=4;
p=&x;
*p=y+4; //执行该语句后,指针 p 中储存的值还是 x 的地址,但 x 的值被改变为 y+4 的值,也就是 8 。
所以通过 *p 间接引用时,大可可以把它当做它指向的变量 x 。
1.2.3统配指针类型void
如果定义:
void *p;
那么指针 p 可以存放任何类型变量的地址,也可以和任何类型的指针相互赋值。
1.2.4 指针与常量限定符conset
如果按如下方式定义:
const int *p=&x; //指针变量 p 的值可以修改但不能通过 *p 来修改 p 所指向变量的值.
int *const p=&x; //指针 p 的值不能修改但能通过 *p 来修改 p 所指向变量的值.这种方式必须给定初值.其中 p 为指针常量
const int *const p=&x; //指针 p 的值不能修改且不能通过 *p 来修改 p 所指向变量的值。
2、指针运算和数组
2.1、指针运算
地址本质上是一个整数,所以对指针进行算术运算是理所当然的,对指针进行算术运算的过程称为指针运算。
指针运算考虑指针的基本类型。
如果对指针变量 p 加 1 , p 的值就会增加一个基本类型的长度。如果 p 指向整型数 ,且 p 的值为 1000,那么 ++p 的结果就是 1004。
2.2 用指针访问数组
数组名本身保存了数组的起始地址,即第 0 个元素的地址。不过数组名为指针常量,其值不能改变,仍然可以进行指针运算。
若定义了整型指针 p 和整型数组 arr,类型一致,因此可以执行 p=arr。
这个时候 p 就可以当做数组 arr 来使用。如 p[0] 。
所以可以通过以下4种方式输出数组的第 i 个元素。
cout<<arr[i];
cout<<*(arr+i);
cout<<p[i];
cout<<*(p+i);
但数组和指针还是存在本质上的区别。
3、动态内存分配
3.1动态变量的创建和消亡
创建用new,消亡用delete.
- 创建
int *p;
p = new int; //new int表示产生一个 int 型的变量,返回其地址给指针变量 p ,变量类型必须与指针类型一致
*p =20; //把产生的变量赋值20
或者
int *p=new int(20); //与上面等效
或者
int *p=new int;
*p=20; //与上面等效
也可以创建一个一位数组
int *p=new int[10];
//或者
int *p;
p=new int[10];
由于中括号内可以是变量,所以可以定义这样一个动态数组:
int n;
cin>>n;
int *p=new int[n];
- 消亡
//格式
delete 指针变量;
//动态变量:
int *p=new int(10);
delete p;
//动态数组
int *p=new int[10];
delete []p;
这样就可以释放掉占用内存了。
3.2、内存泄漏
如果没有使用 delete 便不使用动态变量或动态数组,或者让指针指向另外一个变量,那原来的占用空间就会丢失,但堆管理器会认为我们一直在使用它们,这样一来,对于长时间使用的程序可能会耗尽所有内存,直至崩溃
3.3、查找new的失误
如果空间用完了,则int *p=new int;就会操作失败,返回空指针给 p ,也就是 p=0 。
3.4、拓展
3.4.1、auto与动态分配
auto p1=new auto(10);
自动判断类型
3.4.2、动态数组初始化
C++11中可以:
int *p=new int[5]{1,2,3,4,5};
如果给出初值个数少于数组元素个数,其余的自动赋值为0,多于则new操作失败。
3.4.3、一些细节
- 动态变量或数组,若在全局中定义不再自动赋初值为0.
- 作为局部变量的指针变量消亡了,不代表其所指的内存会释放.所以离开局部变量的范围后动态内存还在。
- 动态内存用 delete 释放后,不代表指针会消亡.
4、字符串再讨论
用指针表示字符串有三种方法
①将一个字符串常量赋给一个指向字符的指针变量,如
char *string="德克萨斯做的到吗!??"
②将一个字符数组名赋给一个指针,字符数组中存储的是一个字符串。
③申请一个动态的字符数组赋给一个指向字符的指针。
其中,①是把储存字符串"abcde"的内存的首地址复制给指针变量string,可以使用 string[i] ,但由于是指向常量的指针,所以不能改变该字符串中任何字符,也不能将该指针作为 strcpy 的参数。
5、指针与函数
5.1、指针作为形参
5.1.1、变量的地址作为函数参数
函数定义或申明可以
void swap(int *a,int *b);
调用可以
swap(&x,&y);
总之就是以传变量地址的方式来对实际参数造成影响。
5.1.2、数组作为函数参数再讨论
通过上面我们就可以更好地认识到——传递数组其实就是把数组的首地址传给形参中定义的数组,也就是指针常量传递给指针常量。
既然如此,假如定义个数组arr,我们也可以传递arr+i;(i是一个整数),如:
void quicksort(int arr[]){};
int main()
{
int arr[10]={1,2,3,4,5,10,6,7,8};
quicksort(arr+4);
}
就相当于把该数组的从下标'4'开始的子数组传递给另一个数组。
当然,我们也可以传递用指针来实现数组组的传递,如:
void quicksort(int *q){};
int main()
{
int arr[10]={1,2,3,4,5,10,6,7,8};
int *q=arr;
quicksort(q+4);
}
但代码是给人看的,我们在设计代码时要让人能看出来这里是干嘛的,功能是什么,要能明确各个参数的用途,为了区分,求其对于初学者来说,传数组就用数组,传指针就用指针。
还有一点值得一提,作为形参定义的数组,它其实应该不能被称作数组,因为它的数组名就是一个指针变量,所以,作为形参定义的数组,其就是定义了一个指针变量,举例如下:
void damedane(int arr[]){};
void damedane(int arr[100]){};
void damedane(char *arr){};
以上三者等价。
参考自: dameyo~
5.1.3、字符串作为函数的参数
其实也就是传递数组,不过重要的是,在使用 cstring 里包含的函数时,我们可以包含指针运算,如:
strncmp(str1+1,str2+5,10);
这样子我们就可以把str1从下标1开始的长度为10的子串和str2小标从5开始的长度为10的子串进行比较了。之前因为求解类似的问题吃了绕了很多弯路,,,现在才知道原来可以这样,,,
对于其他函数也是同理。
5.2、返回指针的函数
返回指针的函数原型为:
<数据类型> *<函数名>(形参);
如函数返回值是一个指向字符的指针,该函数原型为:
char *subString(char *,int,int);
值得注意的是,当函数的返回值是指针是,返回地址的变量可以是全局变量或动态变量……但绝对不能是被调用函数的局部变量,这是因为当被调用函数返回后,局部变量已消失,当使用者通过函数返回的地址去访问地址中的内容时,会发现无权使用该地址。
当然,,,如果你函数里面用的是静态局部变量的话,就当我没说。
5.3、补充~
前面我们知道,可以用 const 来限制 *p 或 p ,在形参里,我们同样可以通过以下方式设计函数原型来限定形式参数:
int naya(const char *);
int naya(char *const);
int naya(const char *const *);
分别可以对应
int naya(const char *str);
int naya(char *const str);
int naya(const char *const *str);
效果可以联系上面内容脑补。
最后
可还行,明天继续,在指针结束的时候对以前的东西做个分类好了,指针这一章节细节和引入的概念有点多,不过还是蛮开心的哈哈哈,不过马上就要期中考了,能不能完成呢~?总之期待着吧!
标签:21,int,指针,地址,数组,new,20.11,变量 来源: https://www.cnblogs.com/Flowyuan-Foreverworld/p/14017759.html