指针和引用的区别:
1)不存在空引用
2)所有的引用都需要初始化
3)一个引用始终指向对他初始化的那个对象
数组作为参数的时候,会退化为指针。同样的例子也发生在函数上。一个函数型参数会退化为一个函数指针。
由于数组形参中数组的边界被忽略了,所以在声明的时候最好将其忽略。然而如果函数期望接受一个指向一个元素序列的指针作为参数的时候,而不是接受单个的指针,那么最好采用如下的申明:
void function(int array[]);
另外如果数组的边界的精确值非常的重要的话,那么可以限制函数只接受特定数量的元素的数组,我们在这种情况下可以考虑采用引用形参:
void function(int (&array)[12] );
现在函数就只能接受大小为12的整形数组了。
模板将有助于代码的泛化:
template<int n> void function(int (&array)[n] ); //让编译器帮助我们推导n的值
当然你也可以采用传统的方法:
void function(int array[], int size);
我们其实也可以将上面的结合起来:
template<int n> inline void function(int (&array)[n] ){ function_1(array,n); }
对于多维数组作为形参而言,形参是一个指向数组的指针,比如我们可以采用:
void function(int (*arr)[20]); //一个指针,指向具有20个元素的的数组
可能下面的方式更加的清晰:
void function(int arr[][20]);
注意对于多维数组,下面的声明是错误的:
int[3][3] arr1={0};
而应该采用下面的方式:
int arr2[3][3]; int arr[3][3]={1,2,3,4,5,6,7,8,9}; int arr[][3]={1,2,3,4,5,6,7,8,9}; //注意,第二个参数不能省略。
指向指针的指针
比如下面的代码:
//将一个指针移动到指向字符串的下一个字符 void function(const char **pstr, char ch){ while(**pstr && (**pstr)!= ch){ ++(*pstr); } }
//将一个指针移动到指向字符串的下一个字符 void function(const char *&pstr, char ch){ while(*pstr && (*pstr)!= ch){ ++(pstr); } }
一个常见的误解就是适用于指针的转换同样适用于指向指针的指针,但是事实并不是如此的,比下面的代码:
class A{ }; class B : public A{ }; int _tmain(int argc, _TCHAR* argv[]) { B * b=new B; A * a=b; //OK. B** b1= &b; A **a1=b1; //Error return 0; }
涉及到const的时候,也有这方面的问题:
我们知道,将一个非常量的指针转换为指向常量的指针是合法的,但是,请看代码:
int * p1=NULL; const int *p2=p1; //OK int * a[100]; //int ** const int **p3=a; //ERROR return 0;