问题1:指针与引用有什么区别?
等级:初级
指针(Pointer)持有另一个对象的地址,使我们能够间接地操作这个对象。引用(Reference)有时候又称为别名,它可以用作对象的另一个名字。它们都是让你间接引用其他对象。
从语法的角度比较,二者主要区别如下:
1) 指针用操作符“*”和“->”,引用使用操作符“.”。
2) 引用在创建的同时必须初始化,即引用到一个有效的对象;而指针在定义的时候可以不初始化,在定义后面的任何地方重新赋值。
3) 指针可以被重新赋值以指向另一个不同的对象。但是,引用则总是指向在初始化时被指定的对象,以后不能改变。
4) “sizeof(引用)”得到的是所指向对象的大小,而“sizeof(指针)”得到的是指针本身的大小。
5) 指针和引用的加法(+)、减法(-)、自增(++)、自减(--)等运算意义不一样。
6) 引用不支持引用数组,指针支持指针数组。
深入讨论:
上述答案可能不够完整,但是基本覆盖了指针和引用的主要区别。可能一些读者还想添加如下两个区别:
1) 不存在NULL引用,引用必须与合法的存储单元关联,而指针则可以是NULL。
2) 程序为指针变量分配内存区域,而引用不分配内存区域。
对此,我不敢苟同。
首先,我们来看看是否存在NULL引用。C++不允许将引用初始化为NULL,所以如下的代码无法通过编译:
char& rc = NULL; // 让引用指向空值 |
但是,使用如下代码,我们就可以创建一个NULL引用,该代码的执行结果将是不确定的。
char *pc = 0; // 设置指针为空值 char& rc = *pc; // 让引用指向空值 |
接着,让我们看看程序是否为引用分配内存区域呢?C++标准并没有对此作出规定,所以我认为这完全取决于编译器,我们不能武断地说程序会或不会为引用分配内存区域。
对于上述指针和引用区别中的第三点,我们可以以另外一种方式来陈述:引用全部是const类型,它总是指向在初始化时被指定的对象;指针有const类型。让我们借用《C++ FAQ》第二版章节11.13中的示例来解释一下这句话。
class Fred { }; void f(Fred& const a); void g(const Fred& const a);
void sample(Fred& a) { Fred& const b = a; const Fred& const c = a; } |
如果在Visual Studio 2008中编译上述代码,你会得到警告信息“anachronism used : qualifiers on reference are ignored”。如果希望去掉该警告信息,我们可以对代码进行如下修改。
class Fred { }; void f(Fred& a); void g(const Fred& a);
void sample(Fred& a) { Fred& b = a; const Fred& c = a; } |
如果使用gcc,你会得到一些错误信息,该程序将无法通过编译。
参考资料:
《More Effective C++》条款1。
《C++ Primer》第四版章节3.2和3.6。
《C++ FAQ》第二版第11章。