已解决:函数重载 原因:临时变量不能作为非const的引用参数传递

#include <iostream>
using namespace std;
double sum(double a,double b)
{
	cout<<"double"<<endl;
	return a+b;
}
long& sum(long& a,long& b)
{
	cout<<"long"<<endl;
	return a;
}
int main(int argc, char *argv[])
{
	int a=1,b=1;
	cout<<sum((long)a,(long)b)<<endl;
	return 0;
}


为什么没有用long函数,而是用的double函数?
找了半天,原来是这样:临时变量不能作为非const的引用参数传递。
因为(long)a会存在一个临时变量中,这个临时变量两个理解:
                  1、没有”名称“,即变量名,没有名称的数据,可以看作是字面量,即常量,显然与long函数类型不符合。
                  2、从非常量来讲,现在临时变量是一个常量,引用它,意味着操作员会再次操作它,事实上,函数一完,它就“消失”。

我们把上面的函数中传来的临时变量、返回的值都加上const ,这样深挖原因:

#include <iostream>
using namespace std;
double sum(double a,double b)
{
	cout<<"double"<<endl;
	return a+b;
}
const long& sum(const long& a,const long& b)
{
	cout<<"long"<<endl;
	
	return a;
}
int main(int argc, char *argv[])
{
	int a=1,b=1;
	cout<<sum((long)a,(long)b)<<endl;
	return 0;
}

这下,临时变量赋予了“合符身份的常量。于是程序就正确地返回了:
long
1

当然,如果改一种修改:直接去掉引用,也能正常显示,但达不到我们分析内在深刻的原因。

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
关于这个,经提问,再百度到了这个:

原址:http://blog.csdn.net/kongying168/article/details/3864756

#include <iostream>
using namespace std; 
void f(int &a)
{
	cout << "f(" << a  << ") is being called" << endl;
} 
void g(const int &a) 
{
	cout << "g(" << a << ") is being called" << endl;
}
int main()
{
	 int a = 3, b = 4;
	 f(a + b);  //编译错误,把临时变量作为非const的引用参数传递了
	 g(a + b);  //OK,把临时变量作为const&传递是允许的
} 


上面的两个调用之前,a+b的值会存在一个临时变量中,当把这个临时变量传给f时,由于f的声明中,参数是int&,不是常量引用,所以产生以下编译错误:
const_ref.cpp: In function `int main()':
const_ref.cpp:14: error: invalid initialization of non-const reference of type '
int&' from a temporary of type 'int'
const_ref.cpp:4: error: in passing argument 1 of `void f(int&)'

而在g(a+b)中,由于g定义的参数是const int&,编译通过。

 问题是为什么临时变量作为引用参数传递时,必须是常量引用呢?

很多人对此的解释是临时变量是常量,不允许赋值,改动,所以当作为非常量引用传递时,编译器就会报错。

这个解释在关于理解临时变量不能作为非const引用参数这个问题上是可以的,但不够准确。事实上,临时变量是可以被作为左值(LValue)并被赋值的,请看下面的代码:


#include <iostream>  
using namespace std; 
class CComplex 
{    
	friend CComplex operator+(const CComplex &cp1, const CComplex &cp2);
	friend ostream& operator<<(ostream &os, const CComplex &cp);
private:  
	 int x;  
public:  
	 CComplex(){}
	 CComplex(int x1)
	 {  
		x = x1;  
	 }
};
CComplex operator+(const CComplex &cp1, const CComplex &cp2) 
{  
	 CComplex cp3;  
	 cp3.x = cp1.x + cp2.x;  
	 return cp3;  
}
ostream& operator<<(ostream &os, const CComplex &cp) 
{
	 os << cp.x;
	 return os;
} 
int main() 
{  
	 CComplex a(2), b(3), c(4);  
	 cout << (a + b) << endl;
	 cout << ((a + b) = c) << endl;   //临时对象作为左值
	 return 0;  
} 



上面的程序编译通过,而且运行结果是:
5

4

临时变量确实被赋值,而且成功了。

所以,临时变量不能作为非const引用参数,不是因为他是常量,而是因为c++编译器的一个关于语义的限制。

如果一个参数是以非const引用传入,c++编译器就有理由认为程序员会在函数中修改这个值,并且这个被修改的引用在函数返回后要发挥作用。

但如果你把一个临时变量当作非const引用参数传进来,由于临时变量的特殊性,程序员并不能操作临时变量,而且临时变量随时可能被释放掉,所以,一般说来,修改一个临时变量是毫无意义的,据此,c++编译器加入了临时变量不能作为非const引用的这个语义限制,意在限制这个非常规用法的潜在错误。

还不明白?OK,我们说直白一点,如果你把临时变量作为非const引用参数传递,一方面,在函数申明中,使用非常量型的引用告诉编译器你需要得到函数对某个对象的修改结果,可是你自己又不给变量起名字,直接丢弃了函数的修改结果,编译器只能说:“大哥,你这是干啥呢,告诉我把结果给你,等我把结果给你了,你又直接给扔了,你这不是在玩我呢吗?”所以编译器一怒之下就不让过了。这下大家明白了吧?




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值