从类方法返回引用的最佳实践是什么?是否要在没有引用的情况下返回基本类型,而要通过引用返回的类对象.您推荐的任何文章,最佳实践文章.
我假设通过类方法你的意思是成员函数.而"通过引用返回"表示"返回对成员数据的引用".这主要是为了返回对本地的引用,这显然是错误的.
什么时候应该返回对成员数据的引用,何时返回数据本身?
默认情况下,您应该返回数据本身(也就是"按值").这避免了返回引用时的几个问题:
用户存储引用并依赖于成员的生命周期,而不考虑包含对象(您的对象)将存活多长时间.导致悬空指针.
用户代码依赖于确切的返回类型.例如,您使用vector
for实现(这是您的getter返回的内容).vector
出现像" " 这样的用户代码.然后你改变你的实现(和getter)来使用deque
- 用户代码中断.如果按值返回,则只需使getter创建一个局部向量,从成员deque中复制数据,然后返回结果.小型收藏品非常合理.[*]
所以什么时候应该返回参考?
当返回的对象是huge(Image
)或不可复制(boost::signal
)时,您可以考虑它.但是,和往常一样,你可以选择更多的OOP模式,让你的班级做一些事情,而不是把东西挂在上面.在这种Image
情况下,您可以提供drawCircle
成员函数,而不是返回Image&
并让您的用户在其上绘制一个圆圈.
当您的数据在逻辑上由您的用户拥有时,您只是为他持有它.考虑std集合:vector
返回对T 的引用,因为这是我想要得到的:我的确切对象,而不是它的副本.
[*]有一种更好的方法可以确保面向未来的代码.而不是返回一个向量(通过ref by value)返回一对迭代器到你的向量 - 一个开始和一个结束.这使您的用户可以使用双端队列或向量执行他们通常执行的所有操作,但与实际实现无关.Boost提供boost::iterator_pair
此目的.作为一个特权,它也有operator []重载,所以你甚至可以做" int i = obj.getItems()[5]
"而不是" int i = obj.getItems().begin()[5]
".
此解决方案适用于任何允许您一般处理类型的情况.例如,如果你保留一个Dog
成员,但你的用户只需知道它是一个Animal
(因为他们只调用eat()
和sleep()
),返回一个Animal引用/指针指向你的狗的freestore分配副本.然后当你决定狗是弱者并且你真的需要一只狼来实现时,用户代码不会破坏.
这种信息隐藏不仅仅是确保未来的兼容性.它还有助于保持您的设计清洁.