引用和指针

来源:互联网 发布:手柄键位设置软件 编辑:程序博客网 时间:2024/05/16 10:01

引用类型
引用reference 有时候又称为别名alias ,它可以用作对象的另一个名字,通过引用我们可以间接地操纵对象,使用方式类似于指针,但是不需要指针的语法,在实际的程序中引用主要被用作函数的形式参数——通常将类对象传递给一个函数但是现在我们用独立的对象来介绍并示范引用的用法
引用类型由类型标识符和一个取地址操作符来定义,引用必须被初始化

例如:
int ival = 1024;
// ok: refVal 是一个指向ival 的引用
int &refVal = ival;
// 错误引用必须被初始化为指向一个对象
int &refVal2;

 


虽然引用也可以被用作一种指针,但是像对指针那样用一个对象的地址初始化引用却是错误的,然而我们可以定义一个指针引用

例如:
int ival = 1024;
// 错误refVal 是int 类型, 不是int*
int &refVal = &ival;


int *pi = &ival;
// ok: refVal2 是一个指向指针的引用
int *&refVal2 = pi;

 


一旦引用已经定义,它就不能再指向其他的对象,这是它为什么必须要被初始化的原因
例如下列的赋值不会使refVal 指向min_val ,而是会使refVal 指向的对象ival 的值被设置为min_val 的值
int min_val = 0;
// ival 被设置为min_val 的值
// refVal 并没有引用到min_val 上
refVal = min_val;

 


引用的所有操作实际上都被应用在它所指的对象身上,包括取地址操作符

例如:
refVal += 2;
将refVal 指向的对象ival 加2 类似地如下语句
int ii = refVal;
把与 ival 相关联的值赋给 ii
int *pi = &refVal;
用ival 的地址初始化pi


const 引用可以用不同类型的对象初始化,只要能从一种类型转换到另一种类型即可,也可以是不可寻址的值如文字常量

例如:
double dval = 3.14159;
// 仅对于const 引用才是合法的
const int &ir = 1024;
const int &ir2 = dval;
const double &dr = dval + 1.0;
同样的初始化对于非const 引用是不合法的,将导致编译错误原因有些微妙需要适当作些解释
引用在内部存放的是一个对象的地址,它是该对象的别名,对于不可寻址的值如文字常量以及不同类型的对象,编译器为了实现引用,必须生成一个临时对象,引用实际上指向该对象,但用户不能访问它,例如当我们写
double dval = 1024;
const int &ri = dval;
编译器将其转换成:

int temp = dval;
const int &ri = temp;
如果我们给ri 赋一个新值,则这样做不会改变dval ,而是改变temp ,对用户来说就好像修改动作没有生效,这对于用户来说这并不总是好事情
const 引用不会暴露这个问题,因为它们是只读的。
下面给出的例子很难在第一次就能正确声明,我们希望用一个const 对象的地址来初始化一个引用,非const 引用定义是非法的,将导致编译时刻错误
const int ival = 1024;
// 错误: 要求一个const 引用
int *&pi_ref = &ival;
下面是我们在打算修正pi_ref 定义时首先想到的做法,但是它不能生效——你能看出来这是为什么吗
const int ival = 1024;
// 仍然错误
const int *&pi_ref = &ival;
如果我们从右向左读这个定义会发现pi_ref 是一个指向定义为const 的int 型对象的指针,我们的引用不是指向一个常量而是指向一个非常量指针,指针指向一个const 对象
正确的定义如下
const int ival = 1024;
// ok: 这是可以被编译器接受的
const int *const &pi_ref = &ival;

 


指针和引用的主要区别:引用必须总是指向一个对象,如果用一个引用给另一个引用赋值,那么改变的是被引用的对象而不是引用本身

让我们来看几个例子

当我们这样写
int *pi = 0;
用0 初始化pi——即pi 当前不指向任何对象但当我们写如下语句时
const int &ri = 0;
在内部发生了以下转换
int temp = 0;
const int &ri = temp;
引用之间的赋值

当给定了以下代码后
int ival = 1024, ival2 = 2048;
int *pi = &ival, *pi2 = &ival2;
我们再写如下语句
pi = pi2;

pi 指向的对象ival 并没有被改变,实际上pi 被赋值为指向pi2 所指的对象——在本例中即ival2 ,重要的是现在pi 和pi2 都指向同一对象
但是假定有下列代码
int &ri = ival, &ri2 = ival2;
当我们写出这样的赋值语句时
ri = ri2;
改变的是ival ,而不是引用本身,赋值之后两个引用仍然指向原来的对象
实际的C++程序很少使用指向独立对象的引用类型,引用类型主要被用作函数的形式参数

例如:
// 在实际的例子中引用是如何被使用的
// 返回访问状态将值放入参数
bool get_next_value( int &next_value );

int ival;
while ( get_next_value( ival )) ...
实际参数本例中为ival 同形式参数next_value 的绑定等价于下面的独立对象定义
int &next_value = ival;

原创粉丝点击