复习C++ (七)复合类型④ 指针

一、储存数据的方式

1.定义简单变量
2.定义指针。

二、找到简单变量的地址

地址运算符&`

cout<<&a;//这样就输出了变量a的地址

三、指针基本介绍

使用常规变量时,值是指定的量,而地址为派生量。
而使用指针变量时,地址是指定的量,值是派生量。
指针这一特殊的变量,储存了一个值的地址。指针名表示的是地址。运算符称为间接值或解除引用运算符,用于指针,可以得到该地址储存的值。若a是一个地址,则a表示地址a中储存的值,变量*a和常规变量int等效。

四、指针声明

指针的声明必须指定指针指向的数据的类型,这是因为计算机内部储存不同数据类型的值时使用的内部格式不同。每个指针都是指向特定的数据类型的。下面这种方式声明的是一个指针和一个普通的int变量

int* a,b;

这说明,声明时,对于每一个指针变量名,都需要一个*。

在声明语句中初始化指针,在这种情况下,被初始化的是指针,而不是它指向的值。

int a=8;
int * p=&a;//这里并不是把&a赋给*p,而是把&a赋给了p

特别注意,创建指针时,计算机将分配用来储存地址的内存,而不好分配储存指针所指向的值的内存。在使用*之前,必须将指针初始化为一个确切的地址。

int * a;
*a=4654798;//由于a没有初始化,a指向的值4654798被存在一个随机的地址,这样对程序来说是危险的

虽然计算机常常将地址当作整数来处理,但他们截然不同,不能简单的将整数赋给指针,即使你知道这个整数是一个地址。应通过强制类型转换来进行这一操作。

int* p;
p=(int*) 0xB8000000;

五、指针如何分配内存

面向对象编程的又一大特定是,在程序运行阶段决策,而不是在程序编译阶段决策。比如,设定数组长度这一工作可以在程序运行阶段进行,即在程序运行阶段创建数组——使用new来分配内存。

1.new的基础用法
前面对指针的初始化,只是指针通过名称访问了某变量的内存,也就是为这一内存提供了别名。指针最大的用处在于,在程序运行阶段分配未命名的内存——使用new运算符。

int* p=new int;//告诉程序,需要一个适合储存int的内存,new运算符找到这样的地址,返回它。

要访问这一内存中的值,只能通过*p的方式。
指明指针所指向的数据类型的必要性在于,在调用这一指针(cout等等)时,知道要读取多少个字节等信息。

new分配的内存是从堆或自由存储区中来的,而普通变量的值储存在名叫栈的内存区域中。C++也提供了检测并处理内存分配失败(如被耗尽)的工具。

与new相对应的是delete,它将不再使用的内存归还给内存池,可供程序的其他部分继续使用。

int* p=new int;
……
delete p;

这样就释放了p指向的内存,但指针p本身还存在,可以给p赋其他的值。new的内存一定要delete,否则被分配的内存无法被程序的其他部分使用(内存泄漏),内存不足会导致程序终止。
delete只能用来释放由new分配的内存,并且不能重复delete同一内存。换言之,在一个程序中,new和delete是一一对应的。

2.使用new创建动态数组
在编译时给数组分配内存被称为静态联编,不管使用与否,数组都被以程序员设定的固定长度创建了。使用new创建动态数组的好处是,如果在运行阶段需要该数组,则创建,否则不创建,创建的数组长度也是在程序运行时选择的,这将减少不必要的内存分配。这是动态联编,创建的数组叫作动态数组。
动态数组例

cin>>size;
int *p=new int [size];
……
delete []p;

①创建

int* pa=new int [8];

new运算返回了第一个元素的地址,该地址被赋给pa。
使用完该内存后,同样需要释放它。

delete [] pa;//[ ]代表了释放的是整个数组的内存。

②使用
访问动态数组的元素时,就像访问数组一样,使用数组名即可。pa[0],pa[1],pa[2]……
但由于指针是变量,数组名不可修改,但指针可以修改

pa=pa+1;

这时,指针指向的元素向后移了一位,pa[0]的值变成了之前pa[1]的值。

③指针算术和数组、指针
数组和指针基本等价是C和C++的特点之一。指针加1,增加的(字节)量等于它指向的数据类型的字节数。C++将数组名解释为数组第一个元素的地址。

double arr[10];
double *pa=arr;//这时把arr[0]的地址赋给了pa;

pa[1]和*(pa+1)是等价的。
数组名和指针的区别在于:1.数组名是常量,指针是变量;2.对数组名sizeof得到的是数组的长度,而对指针sizeof得到的是指针的长度(这种情况下C++不会将数组名解释为地址)。
对数组取地址时,也与数组名不同。数组名被解释为第一个元素的地址,而对数组名应用地址运算符&时,得到的是整个数组的地址。如数组short test[10];tell+1,地址加2,&tell+1,地址加20(整个数组的长度);

六、指针和字符串

在多数C++表达式中,char数组名、char指针以及用引号括起来的字符串常量都被解释为字符串第一个字符的地址。与逐个传递字符串中所有的字符相比,工作量少了。

一般来说,如果给cout提供一个指针,它将打印地址。但是,如果指针类型为char*,将打印指向的字符串。如果要打印该字符串的地址,应强制转换指针类型,比如int*。

……//p是指针
flower="rose";
p=flower;//这时只是把flower的地址赋给了p,所以此时p代表的地址和flower代表的地址、指向的值都是一模一样的

如果只想传递flower的值,而不改变p的地址,则需要

p=new char[strlen(flower)+1];//字符串长加1(包括空字符)
strcpy(p,flower);

这时,p和flower两个地址不同,但内存中的值都是"rose"。
总之,应使用strcpy()或strncpy()而不是=来将字符串赋给数组。

new创建动态结构

结构和数组类似,在运行时创建数组更好。在程序运行时为结构分配内存,也可以用new实现。这样创建的结构称为动态结构。结构和类相似,所以这段技术也适用于类。

structname * p=new structname;

这将创建足以储存structname结构的内存空间并赋给p。
但由于没有变量名,将难以访问结构的成员。
这里提供->代替.。
p->price是被指向的结构的一个成员price。
即结构名用句点,指针名用箭头。
另一种表示方式是(*p).price。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值