C++中的引用

C++中引用和指针的概念常常被拿来对比,二者之间有非常相似的特性。这给初学者带来了困扰,特别是很多编译器使用了指针来实现引用,更增添二者之间扑朔迷离的牵连关系!本文仅就引用的特性做简要介绍,旨在帮助读者更好地理解引用的概念和避免常见的错误!


引用的三大特性

  1. 不存在空引用
  2. 所有引用都要初始化
  3. 引用所指向的对象不可更改

仔细品味以上引用的三大特性,就会发现这三点都是相对于指针而言的。关于这三点,指针有完全相反的特性! 因此以上三点实则也是引用与指针的三大区别!读者应当仔细品之,并牢记于心,绝大多数对引用的误用都滋生与对这三大区别的误解!


引用的本质是别名

引用的三大特性,表面上看似乎是相对于指针的特性总结而来,并与之区别! 但

引用的的本质是别名

确是这三大特性的内在根源, 换句话说引用所指向的对象在赋给引用之前一定要先于引用被创建。这和使用typedef创建类型的别名有异曲同工之妙!

template< typename T1, typename T2>
class MyType
{
   public:
   MyType();
   MyType( const MyType&);  
   void swap( T1&, T2& );
};

int main()
{
   typedef MyType<int, short> TType;

   TType swapper;
   int a = 10;
   short b = 2;
   swapper.swap( a, b );

   return 0;
}

引用的常见错误

double& d = 10.5; //错误

double a = 10.5;
double& d = a;    //正确

错误在哪里呢? 要对此有比较深入的理解涉及到左值,右值,左值引用和右值引用的概念。 为了尽快讲清楚这个问题, 我们对左值,右值的概念做一个简短的介绍。

左值是指表达式结束后依然存在的持久对象
右值对应于临时对象,表达式结束的时候已经不存在

在一个赋值表达式中,等号左边的一般就是左值,右边的一般就是右值。因此有了左值右值的叫法, 但对于左值右值的判断切不可以此作为标准,而应该以定义为准!

上述代码中 d 是一个左值引用, 而 10.5 显然是一个临时对象,因此是一个右值。问题来了,一个非常量左值引用可以绑定到一个右值对象吗? 答案是否定的, 我们可以依据C++标准得到这个答案:

C++标准规定非常量左值引用只能绑定到一个非常量左值

因此上述代码中 d = a 是正确的用法。那么标准为什么会这么规定呢? 设想一个函数:

void swap( double& d1, double& d2);
...
swap(10.0, 1.0);

这段代码是不能通过编译的, 因为显然他违反了上述规范。 这里的swap 函数显然将会修改它的参数,如果我们允许将临时变量作为参数输入, 那我们不能获得修改后的结果。因此输入的参数必须是已经创建好并初始化的实参,这样我们才能够获得函数修改后的结果!这里总结一下:

当一个函数的参数是一个非常量引用的时候, 程序员实际是在暗示编译器该引用所指向的对象将会被函数修改,因此调用者必须确保输入的实参是一个左值(非临时变量)。否则函数所做的修改将无法获取!为了避免由此所造成的危险和不确定性,C++ 规定在此情形下,临时变量不可赋给非常量引用。

那么对于常量左值引用可以绑定到哪些对象呢? 啊, 它简直是所向披靡,见到谁都可以绑上去!

double d = 2.1;
const double  e  = 0.2;
const double& d1 = d + e;
const double& d2 = 1.4;
const double& d3 = d;
const double& d3 = e;

这些情形下他都完全没问题!因此下面这段代码是可以的:

const std::string& s = std::string("Hello ") + "World!";

那么这个呢?

std::string& s = std::string("Hello ") + "World!";
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值