指针与引用是C++中两个很重要的概念,它们功能看过去很相似,就是都是间接引用某个对象,那么我们应该在什么时候使用指针,什么时候使用引用呢,下面请允许我慢慢道来:
-
1.指针和引用的定义和性质区别:
- (1)指针:指针是一个变量,只不过这个变量存储的是一个
地址
,指向内存的一个存储单元;而引用跟原来的变量实质上是同一个东西,只不过是原变量的一个别名
而已。如:
int a=1; int *p=&a; int a=1; int &b=a;
上面定义了一个整形变量和一个指针变量p,该指针变量指向a的存储单元,即p的值是a存储单元的地址;而下面2句定义了一个整形变量a和这个整形a的引用b,事实上a和b是同一个东西,在内存占有同一个存储单元。
- (2)
可以有const指针,但是没有const引用
; - (3)
指针可以有多级,但是引用只能是一级(int **p;合法 而 int &&a是不合法的)
; - (4)
指针的值在初始化后可以改变,即指向其它的存储单元,而引用在进行初始化后就不会再改变了
; - (5)
"sizeof引用"得到的是所指向的变量(对象)的大小,而"sizeof指针"得到的是指针本身的大小
; - (6)
指针和引用的自增(++)运算意义不一样
;
- (1)指针:指针是一个变量,只不过这个变量存储的是一个
-
2.指针和引用作为函数参数进行传递时的区别:
-
(1)指针作为参数进行传递:用指针传递参数,可以实现对实参进行改变的目的,是因为传递过来的是实参的地址;也是将实参的一个拷贝传递给形参;
-
(2)将引用作为函数的参数进行传递:实质上传递的是实参本身,即传递进来的不是实参的一个拷贝,因此对形参的修改其实是对实参的修改,所以在用引用进行参数传递时,不仅节约时间,而且可以节约空间。
-
- 3.永远
不要使用一个指向空值的引用,指针可以为空值
。一个引用必须始终指向某个对象,所以当你确定使用一个变量指向某个对象时,但是这个对象在某些时间可能指向空值,这时候你就必须把变量声明为指针类型,而不是引用!当你确定这个变量始终指向某个对象是,这时候你就可以把变量声明为引用类型。
char *str=0; //设置指针为空值
char &s=*str; //让引用指向空值
//你应该避免出现上面的错误!
- 4.因为引用肯定要指向一个对象,所以,在C++语言里
引用必须被初始化,未初始化的指针合法但危险
。
string& rs; //错误引用必须被初始化
string s("xyzzy");
string& rs = s; //正确rs指向s复制代码
// 指针没有这样的限制
string *ps; //未初始化的指针合法但危险
- 5.不存在指向空值的引用这个事实意味着使用
引用的代码效率比使用指针的要高
,因为在使用引用之前不需要测试它的合法性,相反指针则应该总是被测试防止其为空。
void printDouble(const double& rd)
{
cout << rd; //不需要测试rd,它
} //肯定指向一个double值复制代码相反指针则应该总是被测试防止其为空
void printDouble(const double *pd)
{
if (pd) // 检查是否为NULL
cout << *pd;
}
- 6.指针与引用的另一个重要的不同是
指针可以被重新赋值以指向另一个不同的对象,但是引用则总是指向在初始化时被指定的对象以后不能改变
。
string s1("Nancy");
string s2("Clancy");
string& rs = s1; //rs引用s1
string *ps = &s1; //ps指向s1
rs = s2; //rs仍旧引用s1,但是s1的值现在是"Clancy"
ps = &s2; //ps现在指向s2;s1没有改变
- 7.
重载某个操作符时你应该使用引用
; 最普通的例子是重载操作符[ ]。这个操作符典型的用法是返回一个目标对象其能被赋值。
总的来说在以下情况下你应该使用指针:一是你考虑到存在不指向任何对象的可能,在这种情况下你能够设置针为空;二是你需要能够在不同的时刻指向不同的对象,在这种情况下你能改变指针的指向;如果总是指向一个对象,并且一旦指向一个对象后就不会改变指向,那么你应该使用引用。
实际上"引用"可以做的任何事情"指针"也都能够做,为什么还要"引用"这东西? 答案是"用适当的工具做恰如其分的工作"。 指针能够毫无约束地操作内存中的任何东西,尽管指针功能强大,但是非常危险;如果的确只需要借用一下某个对象的"别名",那么就用"引用",而不要用"指针",以免发生意外。