我一直在考虑使用 unique_ptrshared_ptrown_solution. 。我对后者不以为然,因为我几乎肯定会弄错,但我对两者都有问题 unique_ptrshared_ptr 因为两者都没有准确地捕捉到我想要的东西。我想创建一个明确拥有资源的资源管理器,但是我希望资源管理器也分发对该资源的引用。

如果我使用 unique_ptr 在资源管理器中并分发原始指针,它们有可能逃逸到其他地方(尽管这违反了我认为的类“合同”)。如果我使用 shared_ptr 并分发 weak_ptr, ,没有什么可以阻止调用者转换 weak_ptr 到一个 shared_ptr 并存储它,从而可能创建一个循环,或更糟糕的是,资源的生命周期超出了资源管理器的生命周期。所以我想我正在寻找的是一个可尊敬的 weak_ptr 无法转换为 shared_ptr.

或者我只是想通过代码中一些措辞强硬的注释来执行合同?

感谢您对此可能有的任何想法。

有帮助吗?

解决方案

智能指针如 shared_ptrunique_ptr 当你拥有时是一个很好的工具 拥有 指针。
但对于非拥有指针,即 观察指针, ,使用原始指针就可以了。

在您的设计中,我认为资源管理器是资源的唯一“所有者”,因此您可以简单地拥有某种形式的智能指针 里面 资源管理器。例如,资源管理器可以有一个 std::vector<std::unique_ptr<Resource>> 作为数据成员,甚至更简单 std::vector<Resource> 如果你的 Resource 类被设计为可以正确存储在 std::vector.

然后,资源管理器可以向外部提供非拥有的观察指针,并且原始指针(或 C++ 引用)适合这种情况。

当然,重要的是资源管理器的生命周期要超过“资源客户端”的生命周期。

其他提示

最后,你不能强迫任何人听。询问微软、苹果或任何开源库开发人员,他们都知道这首歌。在正确的词语和位置发表评论是您最好的选择。

避免创建自己的智能指针类,它会阻碍组合并降低可读性。作为最后的手段,尝试查看 boost 或您的代码已经可以使用的任何框架。

如果您有非所有者,他们可以选择持有 weak_ptrs 或(如果保证在持续时间内保持有效)原始指针。
如果你使用 shared_ptr内部(为什么要),最好提供 weak_ptr 和原始指针。

所有这些智能指针都明确表示所有权策略。原始指针表示无或不拥有。

  • auto_ptr:不要使用,即使对于谨慎的人来说,也不推荐使用,因为有太多陷阱。
  • unique_ptr:独家所有权。
  • shared_ptr:共享所有权
  • weak_ptr:没有所有权,可能会被你背后删除。
  • 原始指针
    • 明确无所有权,保证更长的使用寿命
    • 或手动所有权管理。

因此,我想我正在寻找的是一个可推迟的feek_ptr,无法转换为共享_ptr。

你可以分发你的一个小助手类:

template<typename T>
class NonConvertibleWeakPtr
{
public:
   NonConvertibleWeakPtr(const std::shared_ptr<T>& p) : p_(p) {}
   ... // other constructors / assignment operators
   bool expired() const { return p_.expired(); }
   T* operator->() const { return get(); }
   T& operator*() const { return *get(); }
private:
   T* get() const { return p_.lock().get(); }
private:
   std::weak_ptr<T> p_;
};

这比原始指针稍微好一些,因为您可以检查指针是否仍然有效。

用法示例:

std::shared_ptr<int> sp = std::make_shared<int>(5);
{
    NonConvertibleWeakPtr<int> wp(sp);
    if(!wp.expired()) {
        std::cout << *wp << std::endl;
    }
}

然而,用户仍然可以滥用它,例如 std::shared_ptr<T> blah(&(*wp));, ,不过需要多一点犯罪能量。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top