区别:
- 不存在 空引用。引用必须连接到一块合法内存上,但是引用不占内存。
- 引用 一旦被初始化就不能再指向另一个对象,而指针可以随时更改指向。
- 引用 在创建的时候 就 必须初始化。指针 可以在任何时间被初始化。
接下来分别阐述指针和引用的区别
指针
在c++中,指针 p 也是创建出的 对象。在c++primer中对对象的定义是:对象 指的是一块能储存数据,并具有某种类型的 内存空间。比如说 对象a 他有值 和 对应的地址&a。计算机会在运行时为该对象分配存储空间,来储存该对象的值,我们可以通过对象的地址,来访问存储空间中的值。
指针 p 也是 对象! 它也有 它的地址&p 和 储存的值 p。不过 指针 p中存的是 其他的数据地址。可以通过 “ * ” 来访问 p 中存的 地址以达到访问 地址指向的对象。
另外, const 常量化标识符的关键字,经过const 修饰的变量,仅仅在语法上是不可以修改的,但是修饰之后变量的存储位置并不是在常量区。
例如:
int * const P ; // const 在p 前面 p 不可以改 P的指向不可以修改,但是P指向的内容可以修改
int const * P; // *P 不可改 也就是说P指针指向的内容不可以修改
引用
最常说的,也是最好理解的,引用 就是给变量起别名,当你操作某一变量的时候和操作某一引用是完全一样的。
int a;
int & ra = a; //引用ra,
说明:
- & 在此不是求地址运算,是引用的标识符
- & 前面的类型 要求与引用的对象的类型必须一样
- 声明引用时,必须对其进行初始化
- 当声明完毕之后,相当于目标变量有两个别名,不能把该引用名作位其他变量的别名
- 引用知识一个声明,并不是重新定义了一个变量,所以引用不占内存,系统也不会分配储存单元。
- 数组不能建立引用。
引用的应用
引用作位参数:
(引用作为参数,和c语言中用 指针传递是有同样的传递效率的)
#include <iostream>
using namespace std;
int Add (int &r1 ,int &r2)
{
int ret;
return ret = r1 + r2;
}
main()
{
int a,b;
cin>>a>>b;
cout<<Add(a,b)<<endl;
return 0;
}
引用的优点
引用作为参数传递的时候,在内存中并没有产生实参的副本,而是直接对实参进行操作。所以引用,比一般的变量传参效率和空间占有率都要更好。而如果是指针的话,就需要给指针变量分配存储单元,相比引用容易产生错误。
常引用 (const)
语法声明:const 类型标识符 &引用名 = 目标变量名;
常引用的意义就是,不能通过引用对目标变量的值进行修改,提高安全性。
引用作位返回值
说明:(一) 以引用返回函数值,定义函数时需要在函数名前面加 &
(二)引用作为返回值的最大好处就是,在内存中不产生返回值的副本
#include <iostream.h>
float temp; //全局变量temp
float fn1(float r); //声明函数fn1
float& fn2(float r); //声明函数fn2
float fn1(float r)
{
temp = (flaot)(r*r*3.14);
return temp;
}
float& fn2(float r)
{
temp = (float)(r*r*3.14);
return temp;
}
void main()
{
float a=fn1(10.0);
float c=fn2(10.0); // 此方法系统不会生成返回值的副本
cout<<a<<c<<endl;
}
引用做为返回值,必须遵守的规则:
- 不能 返回局部变量的引用。因为局部变量会在函数结束后被销毁,此时如果返回引用的话,那么该引用就会变成“未知指向的引用”
- 不能 返回函数内部new 分配的内存的引用。因为会导致new出来的空间无法被释放。会导致内存泄漏(memory leak)(例如:被返回的引用只是做为一个临时变量,那么引用所指向的空间就无法释放)
- 可以返回类成员的引用,但最好是const。这条原则可以参照Effective C++[1] 的 Item 30。 主要原因是当对象的属性是与某种业务规则(business rule)相关联的时候,其赋值常常与某些其它属性或者对象的状态有关,因此有必要将赋值操作封装在一个业务规则当中。如果其他对象可以获得还属性的 非常引用,那么对该属性的单纯赋值就会破坏业务规则的完整性。
引用和多态
引用时除了指针另外一个可以产生多态效果的手段。也就是说,一个基类指针的引用可以指向它的派生类