[GeekBand] C++ 基础知识一 ——通过引用传递数组
本文参考 : C++ Primer (第四版) 7.2.4及 16.1.5 相关章节
GeekBand 侯捷老师,学习笔记
开发环境采用:VS2013版本
关键问题一、传递引用与传指针、传值的区别?
值传递 (pass by value),指针传递(pass by pointer),当发生函数调用时,需要给形参分配存储单元、当传递是对象时,要调用拷贝构造函数。
而且指针最后析构时,要处理内存释放问题。
引用传递(pass by refenrence),在内存中没有产生形参。效率大大提高!也不用处理指针的析构问题。
通过以上分析,我们设计程序时应该尽量使用引用,少利用指针。如果非得强调类似,”值传递,如”char 类型只有一个字节,请君左转,屏幕右上角有个红叉“
关键问题二:如何传递引用
那么,传递不了指针,我们传递数组怎么样?首先看下下面的简易代码:(C++ Primer 7.2.4)
#include "stdafx.h" #include<iostream> using namespace std; void PrintValues(const int ia[10]) { for (int i = 0; i != 10; i++) { cout << ia[i] << endl; } } int _tmain(int argc, _TCHAR* argv[]) { int j[2] = { 0, 1 }; PrintValues(j); return 0; }
这里因为编译器忽略了为任何数组形参指定长度,所以会造成数组内存越界问题。
而且,数组有二个特性,影响作用在数组上的函数:一是不能复制数组,二是使用数组名时, 数组名会自动指向其第一个元素的指针。因为不能复制,所以无法编写使用数组类型的形参,数组会自动转化为指针。
我们验证下,将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 _tmain(int argc, _TCHAR* argv[]) { 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 _tmain(int argc, _TCHAR* argv[]) { int j[2] = { 0, 1 }; PrintValues(j); return 0; }
结果显示,与pass by pointer方法结果一致,但是这里有一个缺陷,这里面 int (&ia)[2],编译器要检查数组实参和形参的大小。扩展性太差!
最终采用非类型模板解决这个问题,代码如下:
#include "stdafx.h" #include<iostream> using namespace std; template<class T,int N> void PrintValues( T (&ia)[N]) { for (int i = 0; i != N; i++) { cout << ia[i] << endl; } } int _tmain(int argc, _TCHAR* argv[]) { int j[2] = { 0, 1 }; PrintValues(j); return 0; }
结果如图:
通过以上分析, 可以采用非类型模板形参传递中来解决效率问题。