曲径通幽论坛

 找回密码
 立即注册
搜索
查看: 2667|回复: 0
打印 上一主题 下一主题

关于返回对象的总结

[复制链接]

4918

主题

5880

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34387
跳转到指定楼层
楼主
发表于 2013-10-1 12:06:07 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
类的成员函数或独立函数都可以返回对象,并有几种返回方式:

1. 返回指向 const 对象的引用


使用 const 引用的常见原因是为了提高效率,比如函数返回传递给它的对象时,返回引用可以提高效率。比如在下面的例子中,使用 Max() 函数返回两个 Vector 对象中较大的一个:
Vector force1(50, 60);
Vector force2(10,70);

Vector max;

max = Max(force1, force2);


下面有 Max() 函数的两种实现:

[C++] 纯文本查看 复制代码
//版本 1
Vector Max(const Vector & v1, const Vector & v2)
{
	if (v1.big() > v2.big())
		return 1;
	else
		return 2;
}

//版本2
const Vector & Max(const Vector &v1, const Vector & v2)
{
	if (v1.big() > v2.big())
		return 1;
	else
		return 2;
}

首先,返回对象时会调用复制构造函数,而返回引用则不会,因此上面代码中的 版本2 要比 版本1所做的工作更少(不需要调用一个函数,也更不需要复制一个临时对象出来),因此效率更高。
其次,传递到 Max() 中的两个对象参数,都被声明为 const 引用,因此返回类型也必须为 const ,这样才匹配。


2. 返回指向非 const 对象的引用


有两种常见的返回非 const 对象的情形,一个是重载赋值运算符,另一个是重载与 cout 一起使用的 << 运算符。前者旨在提高效率,后者则必须这样做。

比如 operator=() 的返回值用于连续赋值:
String s1("Good girl");
String s2, s3;
s3 = s2 = s1;

在上面代码中,s2.operator=() 的返回值被赋给了 s3。这里返回 String 对象 或 String 对象的引用都是可以的,与上述的 Vector 示例的一样,通过使用引用,可避免该函数调用 String 的复制构造函数创建一个新的 String 对象。在这个例子中,返回类型不是 const,因为 operator=() 返回一个指向 s2 的引用,可以对其进行修改,使用 const 就,不行了。

当 operator<<() 的返回值用于串接输出时有:
String s1("Good girl");
cout << s1 << "is coming!";

在上面代码中,operator<<(cout, s1) 的返回值是一个用以显示字符串 "is coming!" 的对象。返回类型必须是 ostream & ,而不能只是 ostream 。如果返回类型是 ostream,那么就需要调用 ostream 类的复制构造函数,但 ostream 没有公有的复制构造函数。幸运的是,返回 cout 的引用是不会带来任何问题的。

3. 返回对象

如果返回的对象是被调用函数中的局部变量,那么就不应按引用方式返回它,因为被调用函数执行完毕时,局部对象会调用析构函数销毁自己。因此,当控制权回到调用函数时,引用的局部对象将不再存在。在这种情况下,应该返回的是对象而不是引用。通常,被重载的算术运算符属于这一类。在这种情况下,就会存在调用复制构造函数来创建被返回对象的开销,但这无法避免。

4. 返回 const 对象
比如我们重载了一个 + 号运算符: Vector::operator+() ,我们一般会如下使用它来相加两个对象:
net = force1 + force2;

然而,也允许像下面奇异的用法:
force1 + force2 = net;
cout << (force1 + force2 = net).magval() << endl;

在实际应用中,谁都不会这么用,但也不能保证百分之百的不被有些人这么写。这种代码之所以可行,是因为复制构造函数将创建一个临时对象来表示返回值,而 net 就被赋给了该临时对象。然而,当临时对象被用完后,就会被丢弃,而 force1, force2, net 这几个对象都会丝毫无损。如果担心这种奇异的行为被滥用,那么有一种简单的解决方案,就是将返回类型声明为 const Vector ,那么 net = force1 + force2; 是合法语句,而 force1 + force2 = net 就是非法的了。


总之,如果方法或函数要返回局部对象,就应返回局部对象,而不是指向对象的引用。在这种情况下,将使用复制构造函数来生成返回的对象。如果方法或函数要返回一个没有公有复制构造函数的类(如 ostream)的对象,它就必须返回一个指向这种对象的引用。最后,有些方法和函数(如重载的赋值运算符)可以返回对象,也可以返回对象的引用,在这种情况下,应首选返回引用,因为其效率更高。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|曲径通幽 ( 琼ICP备11001422号-1|公安备案:46900502000207 )

GMT+8, 2024-5-21 12:05 , Processed in 0.059772 second(s), 23 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表