#include <iostream>
const float pi = 3.14f ;
float f ;
float f1(float r)
{
f = r*r*pi ;
return f ;
}
float& f2(float r)
{
f = r*r*pi ;
return f ;
}
int main()
{
float f1(float = 5) ;
float& f2(float = 5) ;
float a = f1() ;
float& b = f1() ;
float c = f2() ;
float& d = f2() ;
d+=1.0f ;
cout<<"a = "<<a<<endl ;
cout<<"b = "<<b<<endl ;
cout<<"c = "<<c<<endl ;
cout<<"d = "<<d<<endl ;
cout<<"f = "<<f<<endl ;
return 0 ;
}
上面程序编译时不通过,存在引用错误,所以在这里详细解析下
解析:
这里f1()函数返回的是全局变量f的值,f2()函数返回的是全局变量f的引用。
(1)代码第21行,正确。声明函数f1()的默认参数调用,其默认参数值为5。
(2)代码第22行,正确。声明函数f2()的默认参数调用,其默认参数值为5.
(3)代码第23行,正确。将变量a赋为f1()的返回值。
(4)代码第24行,错误。将变量b赋为f1()的返回值。因为在f1()函数里,全局变量f的值78.5赋给一个临时变量temp,这个temp变量由编译器隐式地建立,然后建立这个temp的引用b。这里对一个临时变量temp进行引用会发生错误。
(5)代码第25行,正确。f2()函数在返回值时并没有隐式地建立临时变量temp,而是直接将全局变量f返回给主函数。
(6)代码第26行,正确。主函数中都不使用定义变量,而是直接使用全局变量的引用,这种方式是全部四种中最节省内存空间的。但必须注意它所引用的变量的有效期,此处全局变量f的有效期肯定长于引用d,所以是安全的。否则,会出现错误。例如,将一个局部变量的引用返回,此时全局变量f的值为78.5。
(7)代码第28行,正确。将d的值加1.0,此时d是全局变量f的引用,因此f的值变成79.5 。
所以注释24和31行后,代码能正常运行,结果为:
A = 78.5 ;
B = 78.5 ;
D = 79.5 ;
F = 79.5 ;
下面程序中同样会出现参数引用的常见错误:(可以尝试着先找找看)
#include <iostream>
using namespace std ;
class Test
{
public:
void f(const int& arg) ;
private:
int value ;
};
void Test::f(const int& arg)
{
arg = 10 ;
cout<<"arg = "<<arg<<endl ;
value = 20 ;
}
int main()
{
int a = 7 ;
const int b = 10 ;
int &c = b ;
const int &d = a ;
a++ ;
d++ ;
Test test ;
test.f(a) ;
cout<<"a = "<<a<<endl ;
return 0 ;
}
把const放在引用之前表示声明的是一个常量引用。不能使用常量引用修改引用变量的值。
(1)代码第14行,错误。因为参数arg是一个常量引用类型的,所以arg的值在函数体内不能被修改。
(2)代码第21和22行,a被声明为整型变量,b被声明为整型常量。
(3)代码第23行,声明c为b的引用,错误。其原因是b为常量,而c不是常量引用。正确的方式应用为:
const int &c = b ;(4)代码第24行,声明d为a 的常量引用,正确。
(5)代码第26行,变量a自增1,正确。
(6)代码第27行,d自增1,错误。d是常量引用,不能对d使用赋值操作。
从上面的分析可以看到,对于常量类型的变量,其引用也必须是常量类型的;对于非常量类型的变量,其引用可以是非常量的,也可以是常量的。但是要注意,无论什么情况,都不能使用常量引用修改其引用的变量的值。
2530

被折叠的 条评论
为什么被折叠?



