C++ 谁应该拥有指针

C++ 谁应该拥有指针,c++,c,pointers,memory-management,C++,C,Pointers,Memory Management,在编程时,我多次遇到以下设计选择:用户创建一个对象并将其传递给另一个对象,该对象在第二阶段以某种方式进行处理 例如,您可以想象一个光线跟踪器。用户创建具有特定属性的球体,并调用raytracer.addTraceable(球体)。现在,我有三种方法可以考虑这样做 光线跟踪器负责释放分配给球体对象的内存 用户需要释放分配给sphere对象的内存 光线跟踪器仅复制球体对象,用户和光线跟踪器都取消分配其本地副本 一般来说,在这种情况下,最好的设计选择是什么?除了我提到的选项(不包括智能指针),还有其他

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

例如,您可以想象一个光线跟踪器。用户创建具有特定属性的球体,并调用
raytracer.addTraceable(球体)
。现在,我有三种方法可以考虑这样做

  • 光线跟踪器负责释放分配给球体对象的内存
  • 用户需要释放分配给sphere对象的内存
  • 光线跟踪器仅复制球体对象,用户和光线跟踪器都取消分配其本地副本
  • 一般来说,在这种情况下,最好的设计选择是什么?除了我提到的选项(不包括智能指针),还有其他选项吗


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

    您似乎意识到智能指针可以为您解决问题,但您拒绝使用它的原因您没有解释。(也许是因为你的代码真的必须同时为C和C++工作)? 如果
    球体
    对象正由
    光线跟踪器
    对象管理,则从逻辑上讲,它将获得对象的所有权。但是,您遗漏了一个适用于此应用程序的选项:

    • 用户提供要添加到
      光线跟踪器
      的对象的属性,然后光线跟踪器负责创建和销毁对象

    然后,“光线跟踪器”(raytracer)变成类似工厂的东西,“属性”(properties)对象变成类似于构建器的东西。

    从设计的角度来看,这三种方法可能都是正确的,总有利弊:

    <> >以AutoPyPTR的形式在C++中改变所有权。缺点是代码维护,例如在raytracer中,您必须始终记住对象是如何分配的,从哪个堆分配的。如果raytracer在具有单独堆的第三方DLL中实现,它将在调试模式下失败,并在发布时出现内存泄漏
  • 若raytracer用户必须释放内存—它必须跟踪raytracer,这意味着它必须拥有所有权,这取决于实现,它可能会增加不必要的代码复杂性
  • 复制对象将是一个完美的解决方案,除非必须在光线跟踪器中跟踪原始球体对象的更改,或者复制会影响性能,或者根本不可能
  • 持续不断地使用这种方法使这一点毫无意义。使用智能指针,如
    std::shared_ptr
    该对象为所有指针所有,并在销毁最后一个指针后将其删除


    C并没有一种方便的方式来表达RAII习语。

    为什么不排除智能指针?你认为显式引用计数是“智能指针”的一部分吗?所以,如果我理解正确的话,在我给出的例子中,光线跟踪器应该处理对象的销毁,因为如果它遇到异常,它是唯一可以这样做的代码?@greerheart,使用智能指针,您不需要担心谁处理销毁。这是自动发生的。我同意标记赎金-在这种情况下,如果适用的话,RAII将是一个选择。不幸的是,作者并没有具体说明他为什么要避免使用智能指针,可能是因为他不能使用第三方库或C++11,但RAII是第四个选项,它并没有前3个选项的任何缺点。有时我必须在一个非常紧密的循环中迭代对象(我正在运行物理模拟)。虽然在我的问题中,我并没有太过具体的描述,但我也希望能有一个解决方案,它可以为C.@ GRIEVREST工作,最好的解决方案是高度依赖于你是否使用C或C++,尽管它们有相似之处和历史,但它们确实是两种不同的语言。最好不要要求两者都有一个解决方案。对于C++来说,没有明显的答案。这与选项3类似,可以使用一个持有属性的代理类。我通常喜欢避免智能指针,因为我正在编写性能关键代码。您确信智能指针会成为应用程序的瓶颈吗?我至少会尝试使用它们,对它们进行基准测试,然后决定是否放弃它们。@格里弗哈特:我不否认这是类似的,但它有效地解决了对象所有权的问题,这正是你的问题所在。在紧循环中使用智能指针的引用,或者在循环中使用指针时获取裸指针本身,可以避免引用计数操作的开销。