什么时候应该从类方法返回对对象的引用

2024-03-03

从类方法返回引用的最佳实践是什么。是否希望在没有引用的情况下返回基本类型,而希望通过引用返回类对象。您推荐的任何文章、最佳实践文章。


我假设你所说的类方法是指成员函数。 “通过引用返回”的意思是“返回对成员数据的引用”。这主要与返回对 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(使用前将#替换为@)

什么时候应该从类方法返回对对象的引用 的相关文章

  • 从实体获取单列

    如何从查询中获取单个列而不是整个对象 我可以这样做来获取整个对象 但我想要的只是名称 IList
  • std::list::clear 是否会使 std::list::end 迭代器无效?

    检查这个代码 include stdafx h include
  • 从 Invoke 方法获取 RETURN

    我正在尝试从另一个线程上的列表框项目中读取值 我尝试创建一种新方法来运行调用命令 我可以设法将命令发送到列表框 例如通过调用方法添加 但我似乎无法得到响应 我似乎无法获取该项目的值 我尝试了几种方法 一旦我将它从空变为字符串 事情就开始变得
  • EventHandler 应该始终用于事件吗?

    我一直在愉快地使用自定义委托类型和通用编写事件Action委托类型 没有真正考虑我在做什么 我有一些很好的扩展助手Action and EventHandler这使我倾向于使用那些预定义的委托类型而不是我自己的委托类型 但除此之外 除了惯例
  • 从另一个 FORM 中取回隐藏的 FORM

    我有两种形式Form1 and Form2 我正在打开Form2 from Form1 on button Click Form2 obj2 new Form2 this Visible false obj2 Show 然后我想回来Form
  • 以下 PLINQ 代码没有改进

    我没有看到使用以下代码的处理速度有任何改进 IEnumerable
  • make_shared<>() 中的 WKWYL 优化是否会给某些多线程应用程序带来惩罚?

    前几天我偶然看到这个非常有趣的演示 http channel9 msdn com Events GoingNative GoingNative 2012 STL11 Magic Secrets作者 Stephan T Lavavej 其中提
  • PrivateObject 找不到属性

    我的结构基本上如下所示 abstract class A protected string Identificator get set private void DoSomething DoSomethingSpecific protect
  • C 类型命名约定,_t 或 ALLCAPS

    我一直想知道是否有任何命名约定 例如何时对类型使用全部大写以及何时追加 t 什么时候不使用任何东西 我知道当时 K R 发布了各种有关如何使用 C 的文档 但我找不到任何相关内容 在 C 标准库类型中 t看起来漂亮占主导地位 time t
  • 提升mapped_file_source、对齐方式和页面大小

    我正在尝试在性能很重要的上下文中解析一些大小高达几百兆字节的文本文件 因此我使用 boostmapped file source 解析器期望源以空字节终止 因此我想检查文件大小是否是页面大小的精确倍数 如果是 则使用较慢的非内存映射方法 我
  • 如何在 EF Core 2.1 中定义外键关系

    我的 DAL 使用 EF Core 2 1 这就是我的模型的样子 一名用户只能拥有一种角色 Role entity kind of master public class Role public int RoleId get set pub
  • MSChart 控件中的自定义 X/Y 网格线

    我有一个带有简单 2D 折线图的 C Windows 窗体 我想向其中添加自定义 X 或 Y 轴标记 并绘制自定义网格线 例如 以突出显示的颜色 虚线 我查看了 customLabels 属性 但这似乎覆盖了我仍然想显示的默认网格 这是为了
  • WinForms - 加载表单时如何使用 PaintEventArgs 运行函数?

    我试图理解图形 在 Graphics FromImage 文档中 它有这样的示例 private void FromImageImage PaintEventArgs e Create image Image imageFile Image
  • 测验;这个编译了吗?如果是的话它会返回什么(我知道答案)

    我最近发现这个错字 if name find string npos 显然开发者的意思是输入 if name find string npos 但令我惊讶的是发现错误甚至编译 Wall Werror 没有尝试过 pedantic 那么 咖啡
  • 在 mvc4 中创建通用 mvc 视图

    我以前也提过类似的问题 没有得到答案 如何创建一个通用的 mvc4 视图 该视图可以显示传递给它的模型列表或单个模型 模型可以是个人 组织或团体 无论传递给它的是什么 如果您正在寻找类似的东西 model MyViewModel
  • 不使用放置 new 返回的指针时的 C++ 严格别名

    这可能会导致未定义的行为吗 uint8 t storage 4 We assume storage is properly aligned here int32 t intPtr new void storage int32 t 4 I k
  • 对多个对象使用事件处理程序

    我有 20 件物品List
  • 在 C 中使用 #define 没有任何价值

    If a define没有任何价值地使用 例如 define COMMAND SPI 默认值是0吗 不 它的评估结果为零 从字面上看 该符号被替换为空 然而 一旦你有了 define FOO 预处理器条件 ifdef FOO现在将是真的 另
  • 如何知道 HTTP 请求标头值是否存在

    我确信这很简单 但是却让我感到厌烦 我在 Web 应用程序中使用了一个组件 它在 Web 请求期间通过添加标头 XYZComponent true 来标识自身 我遇到的问题是 如何在视图中检查此组件 以下内容不起作用 if Request
  • IDisposable 的显式实现

    虽然有很多关于IDisposable在 SO 上找到 我还没有找到答案 我通常遵循这样的做法 当我的一个班级拥有一个IDisposable对象然后它也实现IDisposable并打电话Dispose在拥有的对象上 然而最近我遇到了一个类 它

随机推荐