2.1.1.将引用用作函数参数
与按值传递不同的是,传递引用,函数将可以使用原始数据,似乎与传递指针有着相同的作用。
int wallet1 = 400;
int wallet2 = 500;
cout<<"wallet1 = $"<<wallet1;
cout<<"wallet2 = $"<<wallet2<<endl;
swap(wallet1, wallet2); //调用
cout<<"wallet1 = $"<<wallet1;
cout<<" wallet2 = $"<<wallet2<<endl;
void swap(int & a, int & b) //引用用作函数参数
{
int temp;
temp = a;
a = b;
b = temp;
}
输出:
wallet1 = $400 wallet2 = $500;
wallet1 = $500 wallet2 = $400;
2.1.2.引用的属性和特别之处
需要注意的是1,如果意图是让函数使用传递给它的信息,而不对这些信息进行修改,同时又想使用引用,则应该使用常量引用。例如:
void swap(const int & a, const int & b){}
当编译器发现代码修改了a,b的值,将生成错误信息。
-
需要注意的是2,如果试图把表达式当实参来调用swap这样的函数,大多数编译器将指出这是错误的,而些较老的编译器将发出警告:
Warning: Temporary used parameter 'a' in call to refcube(double &)
原因在于早期的C++确实允许将表达式传递给引用变量,程序将创建一个临时的无名变量,并将其初始化为表达式的值,然后形参将成为该临时变量的引用。
- 临时变量、引用参数和const
当前,仅当参数为const引用时,C++才允许这样做,但以前不是这样。
如果引用参数是const,则编译器将在下面两种情况下生成临时变量:
- 实参的类型正确,但不是左值;
- 实参的类型不正确,但可以转换为正确的类型;
什么是左值?
引用参数是可被引用的数据对象,例如,变量、数组元素、结构成员、引用和解除引用的指针都是左值。非左值包括字面常量和多项表达式。另外,常规变量和const变量都可视为左值,前者属于可修改左值,后者属于不可修改的左值。
double refcube(const double &ra) { return ra * ra * ra; } double side = 2.0; double * pd =&side ; double & rd = side; long edge = 5L; double lens[4] = {2.0, 5.0, 10.0, 12.0}; double c1 = refcube(side); //ra is side double c2 = refcube(lens[2]); //ra is lens[2] double c3 = refcube(rd); //ra is rd is side double c4 = refcube(*pd); //ra is *pd is side double c5 = refcube(edge); //ra is temporary variable double c6 = refcube(7.0); //ra is temporary variable double c7 = refcube(side + 10.0); //ra is temporary variable
参数7.0和side + 10.0的类型都正确,但没有名称,在这些情况下,编译器都将生成一个临时匿名变量,并让ra指向它。这些临时变量只在函数调用期间存在,此后编译器便可以随意将其删除。
如果接受引用参数的意图是修改作为参数传递的变量,则创建临时变量将阻止这种意图的实现,就不要用const引用;若意图只是使用传递的值,则尽可能使用const引用。