引用和指针

引用和指针都属于复合类型(基于其他类型定义的类型)

1、引用

引用为对象起了另外一个名字,引用类型引用另外一种类型。通过声明符写成&d的形式来定义引用类型,其中d是声明的变量名:

int  ival  =  1024;

int  &refval  =  ival;                       //  refval指向ival(是ival的另一个名字)

int  &refval2;                       //  报错: 引用必须被初始化

一般在初始化变量时,初始值会被拷贝到新建的对象中。然而定义引用时,程序会把引用和它的初始值绑定在一起,而不是将初始值拷贝给引用。一旦初始化完成,引用将和它的初始值对象一直绑定在一起。因为无法令引用重新绑定到另一个对象,因此引用必须初始化。

引用并非对象,相反的,它只是为一个已经存在的对象起的另外一个名字。为引用赋值,实际上是把值赋给了与引用绑定的对象。获取引用的值,实际上是获取了与引用绑定的对象的值。同理,以引用作为初始值,实际上是以与引用绑定的对象作为初始值。因为引用本身不是一个对象,所以不能定义引用的引用。

引用的类型必须与其所引用对象的类型一致:

double  dval  =  3.14;

int  &refval  =  dval;              //  错误:此处引用类型的初始值必须是int型对象

const 的引用

可以把引用绑定到const对象上,就像绑定到其他对象上一样,我们称之为对常量的引用。与普通引用不同的是,对常量的引用不能被用作修改它所绑定的对象:

const  int  ci  =  1024;

const  int  &r1  ci;             //  正确:引用及其对应的对象都是常量

r1  =  42;                     //  错误:r1是对常量的引用

int  &r2  =  ci;                     //   错误: 试图让一个非常量引用指向一个常量对象

前面提到:引用的类型必须与其所引用对象的类型一致,但有例外:

double  dval  =  3.14;

const  int  &ri  =  double;

此处ri引用了一个int型函数。对ri的操作应该是整数运算,但dval却是一个双精度浮点数而非整数。因此为了确保ri帮顶一个整数,编译器把上述代码变成如下形式:

const  int  tmp  =  dval;        //  由双精度浮点数生成一个临时的整型常量

const  int  &ri  =  tmp;    //  让ri绑定这个临时量

2、指针

指针是指向另一种类型的复合类型。与引用类似,指针也实现了对其他对象的间接访问。然而指针与引用相比又有很多不同点。其一,指针本身就是一个对象,允许对指针赋值和拷贝,而且在指针的生命周期内它可以指向几个不同的对象。其二,指针无需在定义是赋初值。和其他内置类型一样,在块作用域内定义的指针如果没有被初始化,也将拥有一个不确定的值。

定义指针类型的方法将声明符写成*d的形式,其中d是变量名:

int  *ip;                            //  指向int型对象的指针

double  *dp;                   //指向double型对象的指针

在声明语句中指针的类型实际上被用于指定它所指向对象的类型,所以二者必须匹配。如果指针指向了一个其他的对象,对该对象的操作将发生错误:

double  dval;

double  *pd  =  &dval;//  正确:初始值是double型对象的地址

double  *pd2  =  pd;//  正确:初始值是指向double对象的指针

int  *pi  =  pd;         //  错误:指针pi的类型与pd的类型不匹配

pi  =  &dval;                 //  错误:试图把double型对象的地址赋给int型指针

指针值

指针的值(即地址)应属下列4种状态之一:

1、指向一个对象

2、指向紧邻对象所占空间的下一个位置

3、空指针

4、无效指针

指针和const

与引用一样,也可以令指针指向常量或非常量。类似于常量引用,指向常量的指针不能用于改变其所指对象的值。要想存放常量对象的地址,只能使用指向常量的指针:

const  double  pi  =  3.14;//pi是一个常量,它的值不能改变

double  *ptr  =  π        //错误:ptr是一个普通的指针

const  double  *cptr  =  π        //正确:cptr可以指向一个双精度常量

*cptr  =  42;                         //错误:不能给*cptr赋值

前面提到:指针的类型必须与其所指对象的类型一致,但有例外:

double  dval  =  3.14;       //dval是一个双精度浮点数,它的值可以改变

cptr  =  &dval;                        //正确:但是不能通过cptr改变它的值

允许令一个指向常量的指针指向一个非常量的对象。

最后总结一下:所谓的指向常量的指针和引用,不过是指针或引用”自以为是”罢了,它们觉得自己指向了常量,所以自觉地不去改变所指对象的值。


重点:

★相同点:
●都是地址的概念;
指针指向一块内存,它的内容是所指内存的地址;而引用是一个可以指向该内存并且能自动解引用的  也叫作别名
★不同点:
●指针是一个实体,而引用仅是个别名;

●引用只能在定义时被初始化一次,之后不可变;指针可变;引用“从一而终”,指针可以“见异思迁”;
●引用没有const,指针有const,const的指针不可变;
●引用不能为空指针可以
●“sizeof 引用”得到的是所指向的变量(对象)的大小,而“sizeof 指针”得到的是指针本身的大小;
●指针和引用的自增(++)运算意义不一样;
●引用是类型安全的,而指针不是 (引用比指针多了类型检查)

使用时尽量使用引用在传参的时候,毕竟少了一次拷贝构造;

对于类的引用成员变量在初始化列表中初始化:










  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C语言中的引用指针有一些区别。下面是它们的主要区别: 1. 语法区别:在C语言中,引用使用&符号来获取变量的地址,而指针使用*符号来声明指针变量和解引用指针。 例如: ```c int num = 10; int *p = # // 使用指针获取变量的地址 int &ref = num; // 使用引用获取变量的地址 ``` 2. 操作区别:通过指针可以进行指针运算和修改指针所指向的值,而引用只能在创建时绑定到一个对象,之后无法改变绑定的对象。 例如: ```c int num = 10; int *p = # int &ref = num; *p = 20; // 修改指针所指向的值 ref = 30; // 修改引用所绑定的值 p++; // 指针运算 // ref++; // 错误,引用无法修改绑定对象 ``` 3. 空指针和野指针指针可以具有空值(NULL),即未指向任何有效对象。而引用必须始终引用一个有效对象,没有空引用的概念。 例如: ```c int *p = NULL; // 空指针 // int &ref; // 错误,引用必须初始化绑定到一个对象 ``` 4. 传递方式:通过指针传递参数时,可以修改原始数据。而通过引用传递参数时,可以直接修改原始数据,但不能重新绑定到其他对象。 例如: ```c void modifyByPointer(int *p) { *p = 100; } void modifyByReference(int &ref) { ref = 200; } int num = 10; modifyByPointer(&num); // 通过指针修改原始数据 modifyByReference(num); // 通过引用修改原始数据 ``` 总体而言,指针提供了更多的灵活性和功能,可以进行指针运算和动态内存分配等操作。而引用更加简洁、直观,适用于简单的传递参数和别名的场景。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值