C++——指针

指针和自由存储空间

指针是一个变量,存储的是值的地址。对变量应用地址运算符(&),就可以获得它的位置。将地址视为指定的量,而将值视为派生量,指针用于存储值的地址。因此指针名表示地址,* 运算符被称为解除引用运算符。

指针的危险

C++创建指针时,会分配用来存储地址的内存,但是不会分配用来存储指针所指的数据的内存。

long * fellow;
*fellow = 2333;
fellow 是个指针,但是却没有赋值地址,所以无法知道fellow的值,则不管值是什么,程序会将它解释为存储2333的地址。

指针和数字

指针不是整型,但是计算机通常把地址当做整数来处理。不能将整数赋给指针:

int * pt;
pt = 0xB600000; // 类型不匹配

左边是指向int的指针,但是右边是个整数,应通过强制类型转换将数字转换为合适的地址类型:

pt = (int *) 0xB600000;

使用new来分配内存

int * pn = new int;

newint数据类型分配内存,找到一个长度正确的内存块后返回该内存块的地址,将该地址复制给指针pn

使用delete释放内存

在通过new请求了内存后,使用完需要用delete将内存释放,归还到内存池中,避免内存泄漏。

int * ps = new int;
...
delete ps;

在释放ps指向的内存并不会删除指针ps本身。
注意:

  • 一定要配对使用newdelete
  • 不能使用delete释放声明变量所获得的内存;
int a = 5;
int * pi = &a;
delete pi;//不被允许,因为内存不是通过new分配的
  • new创建数组,则应该使用delete [ ]来释放,总之,如果使用new时,不带方括号,则使用delete时也不应带方括号;
  • 不能使用sizeof运算符来确定动态分配的数组包含的字节数。

指针、数组和指针算术

指针算术

指针变量加1后,增加的量等于它所指的类型的字节数

指针和数组

C++将数组名解释为地址。
short tell[3] = {1,2,3};
C++编译器将tell[1] 看作是*(tell+1)
对数组应用 sizeof 运算符得到的是整个数组的长度,而对指针应用 sizeof 得到的是指针的长度:

double wages[3] = {10.0, 20.0, 30.0};
double * pw = wages;

sizeof(wages)是24个字节,sizeof(pw)是指针字节,与系统有关。

注意:

  • 数组名被解释为其第一个元素的地址,而对数组名应用地址运算符时,得到的是整个数组的地址;
short tell[10];
cout << tell << endl;//是一个2字节内存块的地址
cout << &tell << endl;//是一个20字节内存块的地址
  • 当两个指针指向同一个数组时,两个指针相减,得到两个元素的间隔。

指针和字符串

char flower[10] = "rose";
cout << flower << "s are red\n";

flower是字符r的char元素的地址。如果给 cout 提供一个字符的地址,则它将从该字符开始打印,直到遇到空白字符为止。如果给 cout 提供一个指针,则打印地址。但是如果指针的类型为 char * ,则必须转换为 int * 才显示出地址。

注意:对于数组的字符串、用引号括起的字符串常量以及指针所描述的字符串,都是传递它们的地址。

函数指针

函数指针的基础知识

  1. 获取函数的地址

    只要使用函数名即可,eg:think()是个函数,则 think 就是该函数的地址。

  2. 声明一个函数指针

    声明指向函数的指针必须指定指针指向的函数类型,即应指明函数的返回类型和函数的参数列表。

double pam(int);//原型

double (*pf)(int);//函数指针类型声明

提示:通常先编写函数的原型,然后用(*pf)替代函数名即可。
*pf(int)意味着pf()是一个返回指针的函数,(*pf)(int)意味着pf是一个指向函数的指针。

  1. 使用函数指针来调用函数
    (*pf)扮演的角色与函数名相同
double pam(int);
double (*pf)(int);
pf = pam; //pf是指向pam()函数的指针
double x = (*pf)(5);//利用指针pf来调用pam(),第一种表示法

//C++也允许像使用函数名那样使用pf:
double y = pf(5);//第二种表示法

深入探讨函数指针

const double * f1(const double ar[], int n);
const double * f2(const double [], int);
const double * f3(const double *, int);

这三个函数的参数列表实际上是相同的。
声明一个函数指针:

const double * (*p1)(const double *, int);

//可以在声明的同时进行初始化:
const double * (*p1)(const double *, int) = f1;

//使用C++11的自动推断功能,只能用于单值初始化,不能用于初始化列表
auto p2 = f2;

//前半部分调用指向的函数,显示的是函数的返回值,都是地址;后半部分返回的是这些...地址处的实际值
cout << (*p1)(av,3) << ": " << *(*p1)(av,3) << endl;
cout << p2(av,3) << ": " << *p2(av,3) << endl;

声明一个包含三个函数指针的数组:

const double * (*pa[3])(const double *,int) = {f1,f2,f3};

*pa[3]表明pa是一个包含三个指针的数组。
auto pb = pa;声明了同样类型的数组,pa和pb都是指向函数指针的指针。
pa[i] 和 pb[i] 都表示数组中的指针,则可以使用任意一种函数调用表示法:

const double * px = pa[0](av,3);
const double * py = (*pb[1])(av,3);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值