引用就是某一变量(目标)的一个别名,对引用的操作与对变量直接操作完全一样。引用的声明方法:类型标识符 &引用名=目标变量名;
引用最大的好处就是提高函数效率以及节省空间;
关键问题一、传递引用与传指针、传值的区别?
值传递 (pass by value),指针传递(pass by pointer),当发生函数调用时,需要给形参分配存储单元、当传递是对象时,要调用拷贝构造函数。
而且指针最后析构时,要处理内存释放问题。
引用传递(pass by refenrence),在内存中没有产生形参。效率大大提高!也不用处理指针的析构问题。
通过以上分析,我们设计程序时在形参中数据较为复杂时(比如以对象作为参数),应该尽量使用引用,少利用指针与值传递。
引用只能是"某一"变量的一个别名;具有一经定义就不可更改性;
int a = 10;
int b = 20;
int &c = a; //给变量a定义一个别名c;且c只能是a变量的别名;(如int &c = b 与 c = b; //错误)
数组的引用
int a[10] ={0};
int &b = (&a)[10];
实际应用对比
1 #include "stdafx.h" 2 #include<iostream> 3 using namespace std; 4 void PrintValues(const int ia[10]) 5 { 6 for (int i = 0; i < 10; i++) 7 { 8 cout << ia[i] << endl; 9 } 10 } 11 12 int main() 13 { 14 int j[2] = { 0, 1 }; 15 PrintValues(j); 16 return 0; 17 }
这里因为编译器忽略了为任何数组形参指定长度,所以会造成数组内存越界问题。
而且,数组有二个特性,影响作用在数组上的函数:一是不能复制数组,二是使用数组名时, 数组名会自动指向其第一个元素的指针。因为不能复制,所以无法编写使用数组类型的形参,数组会自动转化为指针。
我们验证下,将Void PrintValues(const int ia[10])改为 Void PrintValues(const int *ia),结果与上图一致,这里就不贴了。
那么怎么解决这个问题呢?
#include "stdafx.h" #include<iostream> using namespace std; void PrintValues(const int *ia,int size) { for (int i = 0; i < size; i++) { cout << ia[i] << endl; } } int main() { int j[] = { 0, 1 }; PrintValues(j,sizeof(j)/sizeof(*j)); return 0; }
此方法虽然可以解决问题,但并不是我们需要的,这部分代码看不出来区别,但工程庞大后,使用引用要比指针高效,所以我们还是要利用引用的特性来解决这个问题。
将数组形参可声明为数组的引用,如果形参是数组的引用,编译器会传递数组的引用本身
我们再修改下代码:如下
#include "stdafx.h" #include<iostream> using namespace std; void PrintValues( int (&ia)[2]) { for (int i = 0; i < 2; i++) { cout << ia[i] << endl; } } int main() { int j[2] = { 0, 1 }; PrintValues(j); return 0; }
结果显示,与pass by pointer方法结果一致,但是这里有一个缺陷,这里面 int (&ia)[2],编译器要检查数组实参和形参的大小。扩展性太差!
#include "stdafx.h" #include<iostream> using namespace std; template<typename T,int N> void PrintValues( T (&ia)[N]) { for (int i = 0; i < N; i++) { cout << ia[i] << endl; } } int main() { int j[2] = { 0, 1 }; PrintValues(j); return 0; }