【问题标题】:Who should own the pointer [closed]谁应该拥有指针[关闭]
【发布时间】:2013-10-07 03:17:01
【问题描述】:

在编程时,我多次遇到以下设计选择:用户创建一个对象并将其传递给其他对象,该对象在第二阶段以某种方式进行处理。

例如,您可以想象一个光线追踪器。用户创建具有某些属性的球体并调用raytracer.addTraceable(sphere)。现在,我可以想到三种方法。

  1. 光线追踪器负责解除分配给球体对象的内存
  2. 用户需要释放分配给球体对象的内存。
  3. 光线追踪器只复制球体对象,用户和光线追踪器都会释放它们的本地副本。

在这种情况下,一般来说最好的设计选择是什么?除了我提到的那些(不包括智能指针)还有其他选择吗?

PS:在使用面向对象的方法时,我在纯 C 语言中遇到了同样的问题。

【问题讨论】:

  • 为什么要排除智能指针?
  • 你认为显式引用计数是“智能指针”的一部分吗?

标签: c++ c pointers memory-management


【解决方案1】:

RAII 的一贯使用使这成为一个争论点。使用诸如std::shared_ptr 之类的智能指针,该对象由 所有 指针拥有,并在最后一个指针被销毁后被删除。

C 并没有真正方便的方式来表达 RAII 习语。

【讨论】:

  • 所以,如果我理解正确,在我给出的示例中,光线追踪器应该处理对象的销毁,因为它是唯一可以在遇到异常时执行此操作的代码?
  • @Grieverheart,有了智能指针,您无需担心谁来处理破坏。它会自动发生。
  • 我同意 Mark Ransom - 如果适用,RAII 将是这种情况下的选择。不幸的是,作者没有说明他为什么要避免使用智能指针,可能是他不能使用 3rd 方库或 C++11,但 RAII 是第 4 个选项,与前 3 个没有任何缺点。
  • 正如我评论 jxh 的帖子。有时我必须在一个非常紧凑的循环中迭代对象(我正在运行物理模拟)。虽然我在我的问题中并没有过于具体,但我也希望有一个适用于 C 的解决方案。
  • @Grieverheart 最好的解决方案在很大程度上取决于您使用的是 C 还是 C++,尽管它们有相似之处和历史,但它们确实是两种不同的语言。最好不要为两者都要求单一的解决方案。 C 没有像 C++ 那样明显的答案。
【解决方案2】:

您似乎意识到智能指针会为您解决问题,但您出于未解释的原因而忽略了它。 (也许是因为你的代码真的必须同时适用于 C 和 C++?)

如果sphere 对象由raytracer 对象管理,那么从逻辑上讲,它拥有该对象的所有权。但是,您遗漏了一个适合此应用程序的选择:

  • 用户提供要添加到raytracer 的对象的属性,然后由raytracer 负责创建和销毁对象。

raytracer 然后就变成了类似工厂的东西,而属性对象就像是构建器。

【讨论】:

  • 这类似于选项 3,可以使用保存属性的代理类。我通常喜欢避免使用智能指针,因为我正在编写性能关键代码。
  • 您确定智能指针会成为您应用程序的瓶颈吗?我至少会尝试使用它们,进行基准测试,然后决定是否放弃它们。
  • @Grieverheart:我不否认它是相似的,但它有效地解决了对象所有权问题,这正是您的问题所在。通过在循环中使用对智能指针的引用或获取裸指针本身,可以在紧密循环中避免引用计数操作的开销。
【解决方案3】:

从设计的角度来看,这三种方式都可能是正确的,但总有优缺点:

  1. 更改所有权在 C++ 中以 auto_ptr 的形式存在。缺点是代码维护,例如在光线跟踪器中,您必须始终牢记对象是如何分配的,从哪个堆分配的。如果光线追踪器是在具有单独堆的 3rd 方 dll 中实现的,它将在调试模式下失败并在发布时出现内存泄漏。
  2. 如果光线追踪器用户必须释放内存 - 它必须跟踪光线追踪器,这意味着它必须拥有所有权,具体取决于实现,它可能会增加不必要的代码复杂性。
  3. 复制对象将是一个完美的解决方案,除非原始球体对象的更改必须在光线跟踪器中进行跟踪或复制会影响性能或根本不可能。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-05
    • 2011-04-13
    • 2020-04-21
    • 2015-10-31
    • 2011-03-18
    • 2013-08-10
    • 2012-05-06
    相关资源
    最近更新 更多