关于函数返回值?

c_hello_world 2009-08-19 07:41:06
今天写了个date类:
其中有一个nextDay()成员函数:就是使时间递增到下一天。
先看看我写的俩版本源代码。
版本1:


myDate myDate::nextDay()
{
static int m[ 13 ] = { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
int tempMonth = getMonth();
myDate tempMd = *this;

tempMd.day += 1;
if( tempMd.day > m[ tempMonth ] )
{
tempMd.day = 1;
tempMd.month += 1;
if( tempMd.month > 12 )
{
tempMd.year += 1;
tempMd.month = 1;
}
}

int y = getYear();

if(( y %400 == 0 )||( y % 100 != 0 && y % 4 == 0 ))
{
if( tempMonth == 2 && tempMd.day == 29 )
{
tempMd.day = 1;
tempMd.month = 3;
}
}

return tempMd;
}

版本2:


myDate& myDate::nextDay1()
{
static int m[ 13 ] = { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
int tempMonth = getMonth();

this->day += 1;
if( this->day > m[ tempMonth ] )
{
this->day = 1;
this->month += 1;
if( this->month > 12 )
{
this->year += 1;
this->month = 1;
}
}

int y = getYear();

if(( y % 400 == 0 )||( y % 100 != 0 && y % 4 == 0 ))
{
if( tempMonth == 2 && this->day == 29 )
{
this->day = 1;
this->month = 3;
}
}

return *this;
}


1:一个版本是返回值类型是:myDate &
2:还有一个版本返回值的类型是:myDate
问题:
1:这两个版本都能实现递增到下一天的功能,那么在实现功能的情况下,使用哪个版本好?【类成员中没有涉及到动态空间分配的情况】
2:这两个版本的效率哪个高?
3:在实现<<重载的情况下,为什么【cout << tday.nextDay();】这样的输出不行,而【cout << tday.nextDay1();】却能实现?
ps:顺便问下一个派生类能继承2个基类?
...全文
162 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
Dave888Zhou 2009-08-19
  • 打赏
  • 举报
回复
这要看你的设计动机了。如果你设计nexDay()成员函数只是为了想看一下today的下一天的值,而不要修改today的值(最典型的情况就是你以后可能还要用到这个today),那当然是用第一种方案了。如果你以后不需要再用到today的值了,那修改它也没关系,应该使用第二种方案,而且效率又高。

对于第一种方案,返回了一个临时对象,你不能直接用引用指向它,否则离开了nextDay()函数后,这个临时对象会销毁,这个引用就变成了悬空的引用。你应该这样:

myDate nextday=today.nextDay();
cout<<nextday;

即定义一个新的myDate对象并初始为函数返回的值(这会调用拷贝构造函数把临时对象拷贝到nextday),然后用cout输出这个值。

  • 打赏
  • 举报
回复
版本1返回副本,而版本2只涉及指针,纯这点来说,效率自然版本2好
飞天御剑流 2009-08-19
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 c_hello_world 的回复:]
引用 9 楼 supermegaboy 的回复:
引用 6 楼 c_hello_world 的回复:
引用 2 楼 kakashi0309 的回复:
  返回引用类型的好呀  这个效率比较高  不会另外产生副本

返回引用的话?
假设运行这样的:
假设:today为2222年2月22日
cout < < today.nextDay();//此时把today的值改成2222年2月23日
如果没有实现减一天功能的成员函数情况下,我想要输出today原来的值,这样似乎没办法实现。
cout < < today;//此时把today值应该为2222年2月23日而不是我想要的2222年2月22日。

这样的问题怎样解决?


此时你可以先保存原值:TempToday = today;

x,y为自己定义的表示分数的类.x 为1/3,y为1/4
cout < < x + y + x < < endl; //我想要的是1/3+1/4+1/3的结果

如果按着你所说的方法,那么就得这样写。
z = x;
cout < < x + y + z < < endl;

是否有直接用cout < < x + y + x < < endl;就能实现的方法?
[/Quote]

那就象我10楼说的那样去做就行了。
太乙 2009-08-19
  • 打赏
  • 举报
回复



1:一个版本是返回值类型是:myDate &
2:还有一个版本返回值的类型是:myDate
问题:
1:这两个版本都能实现递增到下一天的功能,那么在实现功能的情况下,使用哪个版本好?【类成员中没有涉及到动态空间分配的情况】

使用引用的较好:一、是由于少复制一环节,二、毕竟,你修改的是对象本身的成员变量,而不是对象的拷贝,故用this即可。

2:这两个版本的效率哪个高?
不考虑其他,只对比引用和副本,肯定引用效率高。

3:在实现 < <重载的情况下,为什么【cout < < tday.nextDay();】这样的输出不行,而【cout < < tday.nextDay1();】却能实现?
同上,不行的原因是你修改的不是对象本身的成员变量,而是对象副本。在函数外对函数内申明的局部变量的引用是未定义的(栈空间)。

ps:顺便问下一个派生类能继承2个基类?
可以!




andyjuce 2009-08-19
  • 打赏
  • 举报
回复
版本1返回的方式是值传递,如果涉及到地址的返回如字符串返回就会造成内存溢出,而版本2是引用,内存中只有一份数据,上述问题。显然是版本2好。
效率方面引用比值传递好。
至于打印时的调用,cout < < tday.nextDay();已经造成内容丢失,当然打印不出来东西,而且还会造成程序崩溃。
ps:一个派生类完全可以继承多个基类
c_hello_world 2009-08-19
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 supermegaboy 的回复:]
引用 6 楼 c_hello_world 的回复:
引用 2 楼 kakashi0309 的回复:
  返回引用类型的好呀  这个效率比较高  不会另外产生副本

返回引用的话?
假设运行这样的:
假设:today为2222年2月22日
cout < < today.nextDay();//此时把today的值改成2222年2月23日
如果没有实现减一天功能的成员函数情况下,我想要输出today原来的值,这样似乎没办法实现。
cout < < today;//此时把today值应该为2222年2月23日而不是我想要的2222年2月22日。

这样的问题怎样解决?



此时你可以先保存原值:TempToday = today;
[/Quote]
x,y为自己定义的表示分数的类.x 为1/3,y为1/4
cout << x + y + x << endl; //我想要的是1/3+1/4+1/3的结果

如果按着你所说的方法,那么就得这样写。
z = x;
cout << x + y + z << endl;

是否有直接用cout << x + y + x << endl;就能实现的方法?
zjw6861982 2009-08-19
  • 打赏
  • 举报
回复
引用好
zgjxwl 2009-08-19
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 c_hello_world 的回复:]
引用 2 楼 kakashi0309 的回复:
  返回引用类型的好呀  这个效率比较高  不会另外产生副本

返回引用的话?
假设运行这样的:
假设:today为2222年2月22日
cout < < today.nextDay();//此时把today的值改成2222年2月23日
如果没有实现减一天功能的成员函数情况下,我想要输出today原来的值,这样似乎没办法实现。
cout < < today;//此时把today值应该为2222年2月23日而不是我想要的2222年2月22日。

这样的问题怎样解决?

[/Quote]

构造一个临时对象。。。保存它的值就够了啊。。

另外:不要返回临时对象的指针或者引用。。。
其实你这里是间接的返回了临时对象的引用。。
飞天御剑流 2009-08-19
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 c_hello_world 的回复:]
引用 2 楼 kakashi0309 的回复:
  返回引用类型的好呀  这个效率比较高  不会另外产生副本

返回引用的话?
假设运行这样的:
假设:today为2222年2月22日
cout < < today.nextDay();//此时把today的值改成2222年2月23日
如果没有实现减一天功能的成员函数情况下,我想要输出today原来的值,这样似乎没办法实现。
cout < < today;//此时把today值应该为2222年2月23日而不是我想要的2222年2月22日。

这样的问题怎样解决?

[/Quote]

或者,<<重载和nextDay都使用传值,这样也可以:


myDate myDate::nextDay();

.........

ostream& operator<<( ostream &output, myDate md )
{
output << md.year << "/" << md.month << "/" << md.day << endl;

return output;
}


只是效率就比较低了。
飞天御剑流 2009-08-19
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 c_hello_world 的回复:]
引用 2 楼 kakashi0309 的回复:
  返回引用类型的好呀  这个效率比较高  不会另外产生副本

返回引用的话?
假设运行这样的:
假设:today为2222年2月22日
cout < < today.nextDay();//此时把today的值改成2222年2月23日
如果没有实现减一天功能的成员函数情况下,我想要输出today原来的值,这样似乎没办法实现。
cout < < today;//此时把today值应该为2222年2月23日而不是我想要的2222年2月22日。

这样的问题怎样解决?

[/Quote]

此时你可以先保存原值:TempToday = today;
superbtl 2009-08-19
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 c_hello_world 的回复:]
引用 2 楼 kakashi0309 的回复:
  返回引用类型的好呀  这个效率比较高  不会另外产生副本

返回引用的话?
假设运行这样的:
假设:today为2222年2月22日
cout < < today.nextDay();//此时把today的值改成2222年2月23日
如果没有实现减一天功能的成员函数情况下,我想要输出today原来的值,这样似乎没办法实现。
cout < < today;//此时把today值应该为2222年2月23日而不是我想要的2222年2月22日。

这样的问题怎样解决?

[/Quote]nextDay(myDate);传个参数呢?
zgjxwl 2009-08-19
  • 打赏
  • 举报
回复
ostream& operator<<( ostream &output, myDate &md )


第3个问题是因为。。。

cout < < tday.nextDay();
等价于
cout < < 临时myDate对象;

myDate &md做形式参数,自然在传进函数之后。。md引用的临时对象就不存在了。。。

这样。。。对于md的任何操作都是错误的。

ostream& operator<<( ostream &output, myDate md )

写成上面这样的话。。至少

cout < < 临时myDate对象;

不会错。
c_hello_world 2009-08-19
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 kakashi0309 的回复:]
  返回引用类型的好呀  这个效率比较高  不会另外产生副本
[/Quote]
返回引用的话?
假设运行这样的:
假设:today为2222年2月22日
cout << today.nextDay();//此时把today的值改成2222年2月23日
如果没有实现减一天功能的成员函数情况下,我想要输出today原来的值,这样似乎没办法实现。
cout << today;//此时把today值应该为2222年2月23日而不是我想要的2222年2月22日。

这样的问题怎样解决?
zgjxwl 2009-08-19
  • 打赏
  • 举报
回复
楼主在书上有看到一句话吧。。。对于自定义类型。一般返回引用。。引用传的是地址。
而不传引用的话。。。这里会调用拷贝构造函数。。。所以效率自然低一些。。

第3个问题是啥?没描述清楚。。


在C++中。。。累可以多重继承。
飞天御剑流 2009-08-19
  • 打赏
  • 举报
回复
1:这两个版本都能实现递增到下一天的功能,那么在实现功能的情况下,使用哪个版本好?【类成员中没有涉及到动态空间分配的情况】
2:这两个版本的效率哪个高?
-----------------------------------------------------
当然是版本2好啦,版本2不仅不需要调用复制构造函数复制数据,还能实现拼接。



3:在实现 < <重载的情况下,为什么【cout < < tday.nextDay();】这样的输出不行,而【cout < < tday.nextDay1();】却能实现?
---------------------------------------------------------------
版本1返回的是一个由复制构造函数产生的临时对象,返回结束后这个临时对象就析构了,但<<运算符重载的第二个参数却是引用,这就成了对一个已经不存在的对象的引用,其内容是不确定的。而版本2返回的不是临时对象,因此正确。
superbtl 2009-08-19
  • 打赏
  • 举报
回复
C++支持多重继承
有引用的效率一般会高,毕竟不赋值就没临时变量产生
你这个连个版本在返回的时候虽然不产生临时变量 但是赋值的时候就要了,所以还是不要挂引用吧,可读性高。
重载的时候就另当别论了,
<<是要连续传值的,如果没有引用,
a<<b<<c 这个是右操作,b<<c后b的值没有改变,因为改变的是b的一个副本,要是用了引用就可以改变b本身了
kakashi0309 2009-08-19
  • 打赏
  • 举报
回复
返回引用类型的好呀 这个效率比较高 不会另外产生副本
c_hello_world 2009-08-19
  • 打赏
  • 举报
回复
我是楼主,补上<<重载操作符的函数:
ostream& operator<<( ostream &output, myDate &md )
{
output << md.year << "/" << md.month << "/" << md.day << endl;

return output;
}

64,282

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧