运算符重载--函数返回值

举例
#include <iostream>
using namespace std;
class Test
{
public:
 
Test(int a = 0) {cout<<"载入构造函数: "<<a<<" | "<<this<<endl; Test::a = a;}
 
Test(Test &temp){cout<<"载入拷贝构造函数temp.a: "<<temp.a<<" | "<<this; cout<<"   this class name: "<<this->name.c_str()<<endl; Test::a = temp.a;}
 
~Test(){cout<<"载入析构函数!"<<"|"<<this<<endl;}
 
friend Test operator + (Test &,  Test &);    //值返回
 
friend Test& operator ++ (Test &);           //引用返回
public:
 
int a; 
 
string name;
};
Test operator + (Test& temp1, Test& temp2)
{
 
Test result(temp1.a + temp2.a);    //局部变量,调用构造函数
 
cout<<"before operator + return!"<<endl;
 
return result;
}
Test& operator ++ (Test& temp)
{
 
temp.a++;
 
cout<<"before operator ++ return!"<<endl;
 
return temp;
}
int main()
{
 
Test a(100);                                                            // 载入构造函数: 100 | 0013FEE8  //对象a的地址为 0013FEE8  
 
a.name = "a";
 
cout<<"a.name: "<<a.name.c_str()<<endl;        // a.name: a
 
Test c = a + a;                                                       // 打印了中间的4行 //可以看出:当运行+重载函数时,创建了临时对象result,地址为0013FD9C,
                                                                                                                    //当运行c=a+a赋值时,result没有释放,并运行拷贝构造函数创建临时对象0013FEBC
                                                                                                                    //采用临时对象对c赋值后,释放了result对象(地址为0013FD9C)。
cout<<"c地址 | "<<&c<<endl;                            // c地址 | 0013FEBC
 
c.name = "c";                                                        
 
cout<<"c.name: "<<c.name.c_str()<<endl;        // c.name: c
 
cout<<c.a<<endl;                                                // 200
 
c++;                                                                       // before operator += return!
 
cout<<c.a<<endl;                                                // 201
 
system("pause");
}
【结果1】VS2005运行结果:
//红色框中的行为“Test c = a + a; ”语句打印

【结果2】
更改++重载函数为返回值,即Test operator ++ (Test& temp), VS2005运行结果如下:
//红色为Test c = a + a; 黄色为c++
main的流程为:
(1) 创建对象a        //构造函数
(2) 调用operator + 函数,函数中创建result 局部对象result( 0013FD70)-- >函数返回之时,拷贝构造函数创建对象 (0013FEBC)-->
Test c = a + a把对象(0013FEBC)赋值给对象c  -->析构result对象 
(3) 调用operator ++ 函数,在返回之时,使用形参temp (对象c)创建临时对象 -->析构临时对象
由上可以得出
(1)  返回值的被调函数返回时,会调用拷贝构造函数产生临时变量;返回后,如果临时变量没有被“保留”下来,则会被析构,同时被调函数内部的局部对象也被析构。
(2) 与 返回引用的operator ++函数相比, 返回值的被调函数 不产生临时对象

【结果3】
把+重载函数改为返回引用,即friend Test& operator + (Test &,  Test &),VS2005运行结果如下:
//红色为Test c = a + a;
返回引用的operator +函数:
    创建局部变量result (0013FDA0)-->函数返回,析构result。  //不调用拷贝构造函数
赋值语句Test c = a + a; 
    调用拷贝构造函数,创建c对象 (0013FEBC)。 //上面结果出错的原因在于拷贝构造函数的参数代表的对象已经被析构了。


【结论】
明白了:返回值和返回引用的区别在于,如果返回 ,那么被调函数在返回之前需要构造一个临时“值”,这个“值”如果是某个类对象,则需要调用拷贝构造函数;如果返回 引用,那么被调函数在返回之前需要保存一个“引用”类型的临时变量。既然返回类型与局部变量类型无关,那么这个局部变量还有什么用呢?就释放了吧。因此,在函数返回时,局部对象就被释放了。
函数返回时的动作: RETURN语句向函数出口的返回类型守门人报告, 值返回守门人说:”需要返回对象值,你等一下啊!”,于是局部对象在门口等着,值返回守门人告诉主调函数可以返回了,于是主调函数调用拷贝构造函数把等在被调函数出口的局部对象拷贝下来,之后被调函数释放局部对象空间。如果是 引用返回守门人,见到RETURN的对象则会说:”需要返回引用类型,把地址给我,你可以走啦!”,于是局部对象把自己的地扯牌(引用的值)留下,自己释放了。主调函数从引用返回守门人那里得到的只是一个地址。一般,主调函数不需要被调函数的局部变量地址,在不关心被调返回值时,这没关系,还有就是像operaor++的情况,返回的是入参的地址,这是正确的地址。总之,函数返回值会强制转化为函数声明返回值类型,只要保证主调函数需要的类型不会在被调返回时释放就对了!
一般来说 ,当返回值不是本函数内定义的局部变量时就可以返回一个引用。在通常情况下 ,引用返回值只用在需对函数的调用重新赋值的场合,也就是对函数的返回值重新赋值的时候
如果返回值:返回的局部对象,在赋值语句结束之后释放,函数返回时保存的临时变量为该对象;
如果返回引用:返回的局部对象,在函数返回时释放,函数返回时保存的临时变量为该对象的引用(地址);

【指针】
在使用引用参数的场合,假如使用指针的话,可以只传递地址,不复制数据,这对于一般的函数没有任何问题,但是重载运算符却不能对指针单独操作。
修改+重载函数修改为:friend Test operator + (Test *,  Test*);  VS2005编译报错如下:
1>e:\testing\main\main.cpp(10) : error C2803: “operator +”必须至少有一个类类型的形参
1>e:\testing\main\main.cpp(18) : error C2803: “operator +”必须至少有一个类类型的形参
1>e:\testing\main\main.cpp(34) : error C2110: “+”: 不能添加两个指针
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值