参数传递
非引用形参
非引用类型的形参是通过复制对应的实参实现初始化(实参副本来初始化形参),函数内部无法修改实参
本身,只能修改局部的副本值。
1:指针形参
函数的形参是指针类型,也是用实参的指针副本来初始化形参,改变形参指针的指向地址不会影响到外
面的实参,但是如果函数内形参和外面实参的指针都是指向同一个内存地址,那么修改形参指针指向内
存地址的值,将会影响到实参。
int v=4; void Fun(int *p) { cout<<*p<<endl;//输出5 *p=11; cout<<*p<<endl;//输出11,这里修改了形参指针指向地址的值,地址和实参指针指向的地址是同一个,所以函数外面打印这个地址的值是11 p=&v; cout<<*p<<endl;//输出4,这里修改了形参指针指向的地址,只作用于局部副本,实参指向的地址没有改变 } int main() { int i=5; int *p=&i; cout<<*p<<endl;//输出5 Fun(p); cout<<*p<<endl;//输出11 system("PAUSE"); return 0; }
2:const形参
函数使用是非引用的非const或const形参,实参可以是const或者非const,因为这里传递的是实参的副
本给非引用的形参。
void fun(int i)//非引用非const形参 { i+=1;//这里可以修改形参 cout<<i<<endl; } void fun1(const int i)//非引用const形参 { //i+=1;//形参是const,所以函数内部无法修改 cout<<i<<endl; } int main() { int i=1; const int j=2; fun(i);//传递实参i的副本,输出2 fun(j);//传递实参j的副本,输出3 fun1(i);//传递实参i的副本,输出1 fun1(j);//传递实参j的副本,输出2 system("PAUSE"); return 0; }
3:复制实参的局限性
-无法实现修改实参的值
-大型对象作为实参传递时,复制对象付出的时间和存储空间代价过大
引用形参
引用形参是直接关联到其所绑定的对象,而并非这些对象的副本。
下面例子是查找vector中与给定值相同的元素个数和返回指向该元素的迭代器
#include <iostream> #include <vector> using std::cout; using std::endl; using std::vector; vector<int>::const_iterator fun( vector<int>::const_iterator beg, vector<int>::const_iterator end, int value, vector<int>::size_type &count ) { vector<int>::const_iterator res=end; for(;beg!=end;beg++) { if(*beg==value) { if(res==end)//第一次找到值 res=beg; count++; } } return res; } int main() { vector<int> vec; vec.push_back(1); vec.push_back(3); vec.push_back(3); vec.push_back(6); vec.push_back(7); vector<int>::size_type count=0; vector<int>::const_iterator beg=fun(vec.begin(),vec.end(),3,count); cout<<count<<endl; system("PAUSE"); return 0; }
const引用
非const引用形参对类型等比较敏感,而const的引用形参调试过程中发现竟然很多地方都可以过。
void fun(int &i) { i++; cout<<i<<endl; } void fun1(const int &i) { cout<<i<<endl; } int main() { double d=1.1; int i=1; const int j=2; //fun(d);//error 这里函数期待一个非const int类型的引用 fun(i);//ok i是函数期待的非const int类型引用 //fun(j);//error j是const,而函数期待非const fun1(d);// 搞不清楚为什么这里能编译通过 fun1(i);//奇怪,这里也能通过 fun1(j);//ok system("PAUSE"); return 0; }
string类型的非const引用形参需要注意字符面量作为实参
void fun(string &str) { str+="!"; cout<<str<<endl; } int main() { string str("hello kenny"); fun(str); //fun("hello jay");//error 这里字符面量是const char[10],函数要求非const引用 system("PAUSE"); return 0; }
传递指向指针的引用
int *&v1就是一个指向指针的引用,从右至左理解:v1是一个引用,与指向int类型对象的指针相关联,
v1只是一个传递进函数的指针别名
//修改指针指向的地址,而地址的值不变 void fun(int *&v1,int *&v2) { int *p=v2; v2=v1; v1=p; } //交换指针指向地址的值 void fun1(int *&v1,int *&v2) { int p=*v2; *v2=*v1; *v1=p; } int main() { int i=1; int j=2; int *v1=&i; int *v2=&j; cout<<"i="<<i<<" "<<"j="<<j<<endl;//1,2 fun(v1,v2); cout<<"*v1="<<*v1<<" "<<"*v2="<<*v2<<endl;//2,1 cout<<"i="<<i<<" "<<"j="<<j<<endl;//1,2 注意这里只是指针指向的地址交换,而i和j的值没变 fun1(v1,v2); cout<<"i="<<i<<" "<<"j="<<j<<endl;//2,1 这里函数交换的是指针指向地址的值 system("PAUSE"); return 0; }