f(int);//按值传递
f(const int &);//按常引用传递
这两种传递方式都可以保护传递的实参在函数中不被修改。向函数中传递很大的自定义类型对象时,在不要求修改实参的情况下,为了不在函数栈区产生大对象的副本,一般不采用按值传递,而要传递实参的常引用。6 int bad_at(int *,int);
7 int& good_at(int *,int);
8 int main()
9 {
10 int array[4]={1,2,3,4};
11 cout<<"bad_at(array,0)"<<bad_at(array,0)<<endl;
12 cout<<"good_at(array,1)"<<good_at(array,1)<<endl;
13
14 //bad_at(array,2)=30;错误,返回一个值时,函数不能作左值
15 good_at(array,3)=40;//正确,返回一个引用时,函数可以作左值
16 cout<<"good_at(array,3)"<<good_at(array,3)<<endl;
17 return 0;
18 }
3.返回引用常见错误
以下的几种情况违反了上述的原则,有的是编译错误,有的则是更可怕的“返回栈内存”错误,返回栈内存会造成难以发现的逻辑错误。
1. 返回按值传递的形参的引用。函数按值传递参数时,形参是建立在函数栈区的临时变量,函数调用结束时,形参占用的空间将被释放。
例如:
int &f(int a)
{
……
return a;
}
2. 返回函数中声明的局部变量的引用。函数中的局部变量存储在函数栈区,函数调用结束时,局部变量占用的空间将被释放。
例如:
int &f()
{
int a;
……
return a;
}
3. 返回的表达式不能代表一个变量,仅仅代表一个值。return语句中的表达式仅仅代表一个值时,将会把这个值保存在临时变量中,临时变量不能作为左值出现,所以把这样的表达式作为引用返回时,将出现编译错误。
例如:
int &f(int& a)
{
……
return a+1;//编译错误
}