C++ C++;让对象依赖于其他对象是一个好的设计吗?

C++ C++;让对象依赖于其他对象是一个好的设计吗?,c++,oop,C++,Oop,我有一个基本的设计,它由三个类组成:一个数据类,一个Holder类,它保存并管理多个数据对象,Holder类返回的包装器包含对数据对象的引用 问题是包装器不能超过Holder,否则它将包含一个悬空引用,因为Holder负责删除数据对象。但由于包装器的生命周期很短(将其放入函数中,对其数据进行一些计算,并使其超出范围),这应该不是问题,但我不确定这是一个好的设计 以下是我考虑过的一些解决方案: -依靠用户阅读文档,从技术上讲,STL迭代器也会发生同样的情况 -使用shared_ptr确保数据持续足

我有一个基本的设计,它由三个类组成:一个数据类,一个Holder类,它保存并管理多个数据对象,Holder类返回的包装器包含对数据对象的引用

问题是包装器不能超过Holder,否则它将包含一个悬空引用,因为Holder负责删除数据对象。但由于包装器的生命周期很短(将其放入函数中,对其数据进行一些计算,并使其超出范围),这应该不是问题,但我不确定这是一个好的设计

以下是我考虑过的一些解决方案:
-依靠用户阅读文档,从技术上讲,STL迭代器也会发生同样的情况
-使用shared_ptr确保数据持续足够长的时间,但感觉有点过头了
-使包装器在每次使用时都验证其支架是否仍然存在
-有什么想法吗

(我希望每个人都能理解这一点,因为英语不是我的母语)

编辑:如果你想用一种理论性较低的方法,这一切都来自我试图编写的一个小算法来解决数独问题,持有者是网格,数据是每个框的内容(结果或临时假设),包装器是一个框类,其中包含对数据的引用,加上其他信息,如行和列。
我最初没有这样说,因为我想知道在更一般的情况下该怎么做。

要详细说明您已经列出的选项

  • 正如您所建议的,
    shared\u ptr
    是一个不错的选择。除非性能是个问题,否则您应该使用它

  • 切勿在
    Wrapper
    中持有指向
    数据的指针。存储一个句柄,该句柄可用于获取指向相应
    数据的指针。在通过
    包装器
    访问
    数据
    之前,获取
    数据
    对象的指针。如果指针无效,则引发
    异常。如果指针有效,则沿着快乐路径前进


  • 只有通过值返回
    包装器
    ,才能帮助确保调用方不会将其保留在调用范围之外。与“包装器仅在创建它们的持有者的生命周期内有效”的注释或文档结合使用就足够了

    或者当创建
    包装
    时,您决定将
    数据
    的所有权转移到
    包装
    ,并且
    数据
    包装
    一起销毁-但是如果您希望a在不删除
    数据的情况下销毁
    包装
    ,该怎么办?您需要一种方法来选择性地将
    数据的所有权
    放弃给
    持有者

    无论你选择哪一种,你都需要决定什么拥有(即:对
    数据的生命周期负责)以及什么时候——一旦你做到了,如果你愿意,你可以使用智能指针来帮助管理——但他们不会为你做设计决策,你也不能简单地说“哦,我将使用智能指针,而不是考虑它”


    记住,如果没有智能指针就无法管理堆内存,那么也没有必要使用它们来管理堆内存

    “感觉太过分了”为什么?可能是第一个和第三个选择。至少,提供一种检查包装器是否“有效”的方法。至于shared_ptr,这并不是说它太过分了,而是它改变了语义。持有者不再是对象的所有者,也不再控制对象的生存期。所以这取决于它是否与您的用例匹配。在我的设计中,我决定
    Holder
    将是管理
    数据
    生命周期的类,因为让
    Wrapper
    对此负责毫无意义:与
    std::vector
    及其迭代器相比:
    vector
    持有者
    ,迭代器是
    包装器
    。顺便说一下,我不喜欢使用智能指针,因为它们迫使我使用堆内存,而在我的情况下,我可以在堆栈上做任何事情。但是,由于我没有制作STL容器,是否建议使用相同的设计策略?(“如果你这样做,那就是UB”)在有效C++中的第一个小插曲是“总是赞成堆栈”,所以是的,任何地方都可以避免堆分配,这样做。我还想说,一般来说,如果要将“别名”传递给堆栈上的对象,则使用引用而不是指针。这意味着不可能(几乎!)无意中尝试删除该对象。