Part4【程设】指针

指针的概念

  • 内存区的每一个字节有一个编号,这就是“地址”,它相 当于旅馆中的房间号
  • 在地址所标识的内存单元中存放数据,这相当于旅馆房间 中居住的旅客一样
  • 由于通过地址能找到所需的变量单元,我们可以说,地址 指向该变量单元
  • 将地址形象化地称为“指针”

 “存储单元的地址”存储单元的内容”

  • 指向就是通过地址来体现的
  • 由于通过地址能找到所需的变量单元,因此说,地址指向该变量单元
  • 将地址形象化地称为“指针”。意思是通过它能找到以它为地址的内存单元
  • 一个变量的地址称为该变量的“指针”
  • 如果有一个变量专门用来存放另一变量的地址(即指 针),则它称为“指针变量”
  • i_pointer就是一个指针变量。指针变量就是地址变量, 用来存放地址的变量,指針变量的值是地址(即指针)
  • 定义指针变量的一般形式为: 类型 * 指针变量名;类型是为指针变量指定的“基类型

 合法的定义和初始化

float *pointer_3;
char *pointer_4;
int a,b;
int *pointer_1=&a,*pointer_2=&b;

赋值语句可为:
a=5; 等价于 *pointer_1=5;

术语

  • 指针变量只能指向同一基类型的变量
  • 用指针变量在屏幕上显示变量的地址值 指针变量指向的数据类型称为基类型
  • & 取地址运算符。(&a是变量a的地址)
  • * 指针运算符(“间接访问”运算符)【如果: int a=0; int *p=&a, 则在将来的运算中*p就代表a。】
  • 引用指针所指向的变量的值 称为指针的解引用(Pointer Dereference)
  • 空指针: 指针没有指向任何空间 | 空指针用常量NULL表示(NULL的值在C++中被定义0 )| 不能引用空指针指向的值

初始化指针变量

⚫ 指针在使用前必须初始化。
⚫ 和别的变量一样,定义指针不初始化 是一个比较普通的错误。
⚫ 没有初始化的指针可能指向任意地址, 对这些指针作操作可能会导致程序错误。
⚫ NULL是一个特殊指针值,称为空指针。它的值为0。它可被用来初始化一个指针,表示不指向任何地址。

指针和一维数组间的关系

一个变量有地址,一个数组包含若干元素,每个数组元素都有相应的地址指针变量可以指向数组元素(把某一元素的地址放到一 个指针变量中)
所谓数组元素的指针就是数组元素的地址。

int a[10]={1,3,5,7,9,11,13,15,17,19};
int *p;
p=&a[0];

注意:数组名a不代表整个数组, 只代表数组首元素的地址。
“ p=a;”的作用是“把a数组的首 元素的地址赋给指针变量p”,而不是“把数组a各元素的值赋给p ” 。

通过指针引用数组元素

引用一个数组元素,可用下面两种方法:

  1. 下标法,如a[i]或p[i]形式 
  2. 指针法,如*(a+i)或*(p+i) 其中a是数组名,p是指向数组元素的指针变量,其初值p=a

指针和字符串

int main()
{ 
    char *string=“I love China!”;
    cout<<string<<endl;
    return 0;
}

注意一定要在内存空间最后加一个'\0'。

指针与函数

充当形参

普通变量作函数参数—按值调用
形参(parameter)← 实参变量(variable)
指针作函数参数—按地址调用
指针形参(pointer parameter) ← &(variable)
ps:指针变量作函数参数->可以修改实参的值;

C++编译器都是将形参数组名作为指针变量来处理的

引用

引用(reference)是已存在变量的别名(alias),通过引用我们可以间接访问变量, 指针也能间接访问变量,但引用在使用上相对指针更安全。

  • 引用的主要用途是为了描述函数的参数和返回值,特别是为了传递较大的数据变量。
  • 对引用型变量的操作实际上就是对被引用变量的操作。
  • 当定义一个引用型变量时, 必须用已存在的变量对其初始化,于是引用就被绑定在那个变量上,对于引用的改动就是对它所绑定的变量的改动,反之亦然。
数据类型 & 引用变量名 = 变量名;

1、数据类型应与被引用变量的类型相同;
2、&是引用运算符;
3、变量名为已定义的变量;

ex:

int x;
int & refx=x;  refx是一个引用型变量,它被初始化为对整型变量x的引用

当定义一个引用变量后,系统并没有为它分配内存空间。
refx与被引用变量x具有相同的地址,即refx与x使用的是同一内存空间。
对引用变量值的修改就是对被引用变量的修改,反之亦然。

x=3;
cout<<refx; //结果为3
refx=5;
cout<<x; //结果为5

从物理实现上看,引用是一个隐性的指针。
引用封装了指针的特性,它不直接操作地址,不能由强制类型转换而得,因而具有较高的安全性。
也不容易产生由于使用指针而常常产生的那些不易觉察的错误。

注意!

1、定义引用时必须立即对它初始化,不能定义完成后再赋值。

int i;
int &j; "错误!!!"
j=i;

2、为引用提供的初始值可以是一个变量或另一个引用。(可以套娃)

3、引用不可重新赋值,不可使其作为另一变量的别名。

int i, k;
int &j=i;
j=&k; "错误"

C++引入引用的主要目的是将引用作为函数的参数。
实参必须是变量,而不能是一个表达式。
引用作为函数的返回值

函数返回值类型为引用型,在函数调用时,若接受返回值的是一个引用变量,相当于定义了一个对返回变量的引用。
若接受返回值的是一个非引用变量,函数返回变量的值赋给接受变量。
如果函数返回值类型为引用型,则要求返回值为左值。
这样,函数调用式可以当作左值。

int& max(int a[],int n) //求数组a[]中元素的最大值
{
    int t=0;
    for(int i=0;i<n;i++)
        if(a[i]>a[t]) t=i;
    return a[t];
}
int& sum(int a[ ],int n) //求数组a[]中元素的和
{
    int s=0;
    for(int i=0;i<n;i++)
        s+=a[i];
    return s;
}

int main()
{
    int a[10]={1,2,3,4,5,6,7,8,9,10};
    int m2=max(a,10);
    int &m3=max(a,10);
    int &m4=sum(a,10);
    cout<<"m2="<<m2<<endl;
    cout<<"m3="<<m3<<endl;
    cout<<"m4="<<m4<<endl;
    m3+=10;
    max(a,10)-=100;
    cout<<sum(a,10)<<endl;
    return 0;
}

常引用

const 数据类型& 引用变量 = 变量名;

定义一个常引用后,就不能通过常引用更改引用的变量的值。

常引用类型常用作函数的形参类型,把形参定义为常引用类型时。
这样在函数体内就不能通过形参改变实参的值,保证了函数调用时实参是“安全”的。
这样的形参称为只读形参。

注意:
形参为常引用类型时,实参可以是常量、变量表达式;
但如果为非常引用类型时,实参必须为左值。
对void fun(const int& x, int& y), 调用fun(100,200)是错误的,!
调用fun(100,a)是正确的【a为变量】。

动态内存分配

有时我们并不知道我们需要多大的数组直到程序开始运行。
因此希望能在程序中根据某一个当前运行值来决定数组的大小。
如要输入学生成绩存入数组,但是学生的数量需要在程序运行时输入,比如我们希望能这样:
int n;
cin>>n;
int scores[n];实际上不能这样。

C++中由new 和 delete两个运算符
运算符new用于进行内存分配:

  • 申请动态变量:p = new type;
  • 申请动态数组:p = new type[size];
  • 申请动态变量并初始化:p = new type(初值);

运算符delete释放new分配的内存:

  • 释放动态变量:delete p;
  • 释放动态数组:delete [] p;
int main()
{
    char *q;
    q = new char[10];
    strcpy(q, "abcde");
    cout << q << endl;
    delete []q;
    return 0;
}

ps:new操作失败时,返回空指针。

int *p;
p = new int;
if(!p) 
{
    cout << "allocation failure\n";
    return 1;
}

指针数组

类型名*数组名[数组长度];

  • 指针数组比较适合用来指向若干个字符串,使字符串处理更加方便灵活 
  • 可以分别定义一些字符串,然后用指针数组中的元素分别指向各字符串
  • 由于各字符串长度一般是不相等的,所以比用二维数组节省内存单元

函数的指针

就是指向函数的指针,指向函数代码的起始地址。

"定义方法"
int isdigit(int n, int k);
{
    ...
}
int (*p)(int, int );
p=isdigit; 

"使用方法"

a=isdigit(n,k);
a=p(n,k)

常见错误

  1. 指针p未赋值就使用*p
  2. 指针p的值为NULL却使用*p
  3. 指针p指向动态内存,但该内存已 被delete了,再使用*p
  4. 指针指向动态内存,但该内存被 delete两次
  5. 指针指向动态数组,但数组在操作时 曾经下标越界,然后delete时会崩溃
  6. 指针指向普通数组,delete时会崩溃
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值