VC++引用类型与指针类型
两种类型的参数都允许有效地向函数传递大型类对象
- 引用必须被初始化为指向一个对象,一旦初始化了它就不能再指向其他对象。指针可以指向一系列不同的对象,也可以什么都不指向。因为指针可能指向一个对象或没有任何对象,所以函数在确定指针实际指向一个有效的对象之前,不能安全地解引用dereference 一个指针。例如
class X;
void manip( X *px )
{
// 在解引用指针之前确信它非0
if ( px != 0 )
// 解引用指针
} - 另一方面,对于引用参数,函数不需要保证它指向一个对象,引用必须指向一个对象,
甚至在我们不希望这样时也是如此。例如
class Type { };
void operate( const Type& p1, const Type& p2 );
int main() {
Type obj1;
// 设置 obj1 为某个值
// 错误: 引用参数的实参不能为0
Type obj2 = operate( obj1, 0 );
}
如果一个参数可能在函数中指向不同的对象,或者这个参数可能不指向任何对象,则必
须使用指针参数。 - 引用参数的一个重要用法是,它允许我们在有效地实现重载操作符的同时,还能保证用
法的直观性。(重载操作符的完整讨论见第15 章)让我们从下面的例子开始它使用了Matrix
类类型,我们想支持两个Matrix 类对象的加法和赋值操作符,使它们的用法同内置类型一样
自然。
Matrix a, b, c;
c = a + b;
Matrix 类对象的加法和赋值操作符用重载操作符来实现。被重载的操作符是一个带有特
殊名字的函数。(在加法操作符的例子中函数名是operator+ )让我们为这个重载操作符提供
一个定义。
Matrix // 加法返回一个Matrix 对象
operator+( // 重载操作符的名字
Matrix m1, // 操作符左操作数的类型
Matrix m2 // 操作符右操作数的类型
)
{
Matrix result;
// do the computation in result
return result;
} - 该实现支持两个Matrix 对象的加法如
a + b
但不幸的是它的效率低得让人难以接受。注意operator+()的参数不是引用,这意味
着operator+()的实参是按值传递的两个Matrix。( 对象a 和b 的内容被拷贝到opertor+()函数
的参数区中)因为Matrix 类对象非常大,分配这样一个对象并把它拷贝到函数参数区中的时
间和空间开销高得让人难以接受。
为了提高我们的操作符函数的效率,假定我们决定把参数声明为指针。下面是对
operator+()新的实现代码
// 使用指针参数重新实现
Matrix operator+( Matrix *m1, Matrix *m2 )
{
Matrix result;
// 在 result 中计算
return result;
}
但是这个实现代码有这样的问题。虽然我们获得了效率,但是它是以放弃加法操作
符用法的直观性为代价的。现在指针参数要求我们传递地址作为实参,它们指向我们希望做
加法操作的Matrix 对象。现在我们的加法操作必须如下编程
&a + &b; // 不太好, 但也不是不可能
但是这比较难看而且可能引起一些程序员抱怨用户接口不友好在一个复合表达式
中加三个对象变得很困难
// 喔! 这无法工作
// &a + &b 的返回类型是 Matrix 对象
&a + &b + &c;
为了使在指针方案下三个对象的加法能够很好地实现程序必须这样写
// ok: 这样能行, 但是
&( &a + &b ) + &c;
当然没有人希望那样写引用参数提供了我们需要的方案当参数是引用时函数接
收到的是实参的左值而不是值的拷贝因为函数知道实参在内存的什么位置所以实参值没
有被拷贝到函数的参数区引用参数的实参是Matrix 对象本身这允许我们像对内置数据类
型的对象使用加法操作符一样自然地使用加法操作符
下面是Matrix 类的重载加法操作符的修订版本
// 使用引用参数的新实现
Matrix operator+( const Matrix &m1, const Matrix &m2 )
{
Matrix result;
// 在 result 中进行计算
return result;
}
该实现支持如下形式的Matrix 对象的加法
a + b + c