5

我一直在考虑使用unique_ptrvs shared_ptrvs own_solution。我对后者打了折扣,因为我几乎肯定会弄错,但我对两者都有问题,因为两者都unique_ptr不能shared_ptr准确地捕捉到我想要的东西。我想创建一个明确拥有资源的资源管理器,但是我希望资源管理器也分发对资源的引用。

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

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

感谢您对此的任何想法。

4

3 回答 3

9

In the end, you cannot force anyone to listen. Ask at microsoft, apple or any open source library developer, they all know that song. A comment in the right words and places is your best bet.

Avoid creating your own smart pointer class, it hinders composition and reduces readability. As a last resort, try looking in boost, or any framework your code already has to work with.

If you have non-owners, they are either electable for holding weak_ptrs or (if it is guaranteed to stay valid for the duration) raw pointers.
If you use shared_ptrs internally (why should you), best provide weak_ptr and raw pointers.

All those smart pointers explicitly denote an ownership policy. Raw pointers denote none or non-owning.

  • auto_ptr: Do not use, deprecated with too many traps even for the wary.
  • unique_ptr: Sole ownership.
  • shared_ptr: Shared ownership
  • weak_ptr: No ownership, might get deleted behind your back.
  • raw pointer
    • Explicitly no ownership with guaranteed bigger lifetime
    • or manual ownership management.
于 2014-04-11T15:34:00.430 回答
6

当您拥有指针时,智能指针喜欢shared_ptr并且unique_ptr是一个很好的工具。 但是对于非拥有指针,即观察指针,使用原始指针就可以了。

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

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

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

于 2014-04-11T15:46:37.473 回答
3

所以我想我正在寻找的是一个无法转换为shared_ptr的可延迟weak_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));,但它需要更多的犯罪能量。

于 2014-04-11T15:53:54.847 回答