从类方法返回引用的最佳实践是什么。是否希望在没有引用的情况下返回基本类型,而希望通过引用返回类对象。您推荐的任何文章、最佳实践文章。
我假设你所说的类方法是指成员函数。 “通过引用返回”的意思是“返回对成员数据的引用”。这主要与返回对 local 的引用相反,这显然是错误的。
什么时候应该返回对成员数据的引用,什么时候返回数据本身?
默认情况下,您应该返回数据本身(也称为“按值”)。这避免了返回引用时出现的几个问题:
用户存储参考并变得依赖lifetime您的成员,而不考虑包含对象(您的对象)的生存时间。导致悬空指针。
用户代码变得依赖于确切的返回类型。例如,您使用vector<T>
用于实现(这就是你的 getter 返回的内容)。用户代码如“vector<T> foo = obj.getItems()
” 出现。然后您更改您的实现(和 getter)以使用deque<T>
-- 用户代码中断。如果您一直按值返回,则可以简单地让 getter 创建一个本地向量,从成员双端队列复制数据,然后返回结果。对于小型收藏来说相当合理。 [*]
那么什么时候应该返回引用呢?
- 当返回的对象很大时可以考虑(
Image
) 或不可复制 (boost::signal
)。但是,与往常一样,您可以选择更 OOP 的模式来让您的课程do东西而不是拥有东西挂在上面。在里面Image
案例,您可以提供drawCircle
成员函数,而不是返回Image&
并让你的用户在上面画一个圆圈。
- 当您的数据逻辑上归您的用户所有,而您只是为他保留它时。考虑 std 集合:
vector<T>::operator[]
返回一个参考到 T 因为这就是我想要得到的:我的确切对象,而不是它的副本。
[*] 有一种更好的方法来确保代码面向未来。不是返回一个向量(通过值的引用),而是向向量返回一对迭代器——一个开始和一个结束。这可以让您的用户一切它们通常使用双端队列或向量,但与实际实现无关。升压提供boost::iterator_pair
以此目的。作为额外的好处,它还重载了operator[],所以你甚至可以这样做“int i = obj.getItems()[5]
“ 而不是 ”int i = obj.getItems().begin()[5]
".
该解决方案可推广到任何允许您通用地处理类型的情况。例如,如果您保留一个Dog
会员,但您的用户只需要知道它是Animal
(因为他们只调用eat()
and sleep()
),返回一个Animal指向您的狗的免费存储分配副本的引用/指针。然后,当您确定狗是弱者并且您确实需要狼来实现时,用户代码将不会中断。
这种信息隐藏不仅仅确保未来的兼容性。它还有助于保持您的设计简洁。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)