翻译自 http://www.geeksforgeeks.org/references-in-c/
原文:
References vs Pointers
Both references and pointers can be used to change local variables of one function inside another function. Both of them can also be used to save copying of big objects when passed as arguments to functions or returned from functions, to get efficiency gain.
Despite above similarities, there are following differences between references and pointers.
A pointer can be declared as void but a reference can never be void
For example
int a = 10;
void* aa = &a;. //it is valid
void &ar = a; // it is not valid
References are less powerful than pointers
1) Once a reference is created, it cannot be later made to reference another object; it cannot be reseated. This is often done with pointers.
2) References cannot be NULL. Pointers are often made NULL to indicate that they are not pointing to any valid thing.
3) A reference must be initialized when declared. There is no such restriction with pointers
Due to the above limitations, references in C++ cannot be used for implementing data structures like Linked List, Tree, etc. In Java, references don’t have above restrictions, and can be used to implement all data structures. References being more powerful in Java, is the main reason Java doesn’t need pointers.
References are safer and easier to use:
1) Safer: Since references must be initialized, wild references like wild pointers are unlikely to exist. It is still possible to have references that don’t refer to a valid location (See questions 5 and 6 in the below exercise )
2) Easier to use: References don’t need dereferencing operator to access the value. They can be used like normal variables. ‘&’ operator is needed only at the time of declaration. Also, members of an object reference can be accessed with dot operator (‘.’), unlike pointers where arrow operator (->) is needed to access members.
Together with the above reasons, there are few places like copy constructor argument where pointer cannot be used. Reference must be used pass the argument in copy constructor. Similarly references must be used for overloading some operators like ++.
译文:引用VS指针
相同点:
- 都可以在一个函数中修改位于另一个函数内的局部变量。
- 都可以以“按引用传递”的方式传递函数参数,避免了“按值传递”方式向函数传递/从函数返回自定义类型的数据时调用复制构造函数,以及复制大量数据,从而提高了时间和空间效率。
- 指针可以是void* 类型的,引用则不可以
- 引用的对象在初始化以后就不可以再修改,相当于 TYPE *const ptr_name (指针常量)
- 指针可以设置为NULL,表示不指向任何有效的对象,而必须有效的初始化,不能设置为NULL
- 引用在声明时必须初始化,而指针没有这个限制
由于以上原因,指针几乎可以用在所有的场合,除了复制构造函数的参数中,复制构造函数的参数必须使用引用,同理,引用也必须用在重载某些操作符时,比如++
Exercise:
Predict the output of following programs. If there are compilation errors, then fix them.
Question 1
#include<iostream>
using namespace std;
int &fun()
{
static int x = 10;
return x;
}
int main()
{
fun() = 30;
cout << fun();
return 0;
}
Question 2
#include<iostream>
using namespace std;
int fun(int &x)
{
return x;
}
int main()
{
cout << fun(10);
return 0;
}
Question 3
#include<iostream>
using namespace std;
void swap(char * &str1, char * &str2)
{
char *temp = str1;
str1 = str2;
str2 = temp;
}
int main()
{
char *str1 = "GEEKS";
char *str2 = "FOR GEEKS";
swap(str1, str2);
cout<<"str1 is "<<str1<<endl;
cout<<"str2 is "<<str2<<endl;
return 0;
}
Question 4
#include<iostream>
using namespace std;
int main()
{
int x = 10;
int *ptr = &x;
int &*ptr1 = ptr;
}
Question 5
#include<iostream>
using namespace std;
int main()
{
int *ptr = NULL;
int &ref = *ptr;
cout << ref;
}//错误:给引用赋值 NULL
Question 6
#include<iostream>
using namespace std;
int &fun()
{
int x = 10;
return x;
}
int main()
{
fun() = 30;
cout << fun();
return 0;
}//返回的是局部变量的引用,编译器会报错
warning: reference to local variable 'x' returned [-Wreturn-local-addr]
指针引用
#include<iostream>
using std::cout;
using std::endl;
void increament(int *&i){i++;}
int main(){
int *i = 0;
cout<<"i = "<<i<<endl;
increament(i);
cout<<"i = "<<i<<endl;
}
输出结果
i = 0
i = 0x4