我一直在考虑使用unique_ptr
vs shared_ptr
vs own_solution
。我对后者打了折扣,因为我几乎肯定会弄错,但我对unique_ptr
和shared_ptr
都有问题,因为它们都没有准确捕捉到我想要的东西。我想创建一个显式拥有资源的资源管理器,但是我希望资源管理器也能分发对该资源的引用。
如果我在资源管理器中使用unique_ptr
并分发原始指针那么他们可能会逃到其他地方(虽然这会违反课程"合同"我想) 。如果我使用shared_ptr
并分发weak_ptr
,则无法阻止调用者将weak_ptr
转换为shared_ptr
并将其存储,从而可能会创建一个循环或者更糟糕的是,资源生活在资源管理者的生命周期之外。所以我想我正在寻找的是一个无法转换为weak_ptr
的可用shared_ptr
。
或者我只是想在代码中用一些措辞强硬的评论强制执行合同?
感谢你对此有任何想法。
答案 0 :(得分:10)
最后,你不能强迫任何人听。在微软,苹果或任何开源图书馆开发人员询问时,他们都知道这首歌。正确的词语和地方的评论是你最好的选择。
避免创建自己的智能指针类,它会阻碍构图并降低可读性。作为最后的手段,请尝试查看boost或您的代码已经使用的任何框架。
如果您拥有非所有者,则他们可以选择持有weak_ptr
或(如果保证在此期间保持有效)原始指针。
如果你在内部使用shared_ptr
(为什么要这样做),最好提供weak_ptr
和原始指针。
所有这些智能指针都明确表示所有权政策。原始指针表示无或不拥有。
auto_ptr
:不要使用,即使是警惕也不要使用太多陷阱。unique_ptr
:独家所有权。shared_ptr
:共享所有权weak_ptr
:没有所有权,可能会被删除。答案 1 :(得分:6)
当您拥有拥有指针时,shared_ptr
和unique_ptr
等智能指针是一个很好的工具。
但是对于非拥有指针,即观察指针,使用原始指针就可以了。
在您的设计中,我认为资源经理是唯一的&#34;所有者&#34;的资源,所以你可以简单地在资源管理器中使用某种形式的智能指针 。例如,如果您的std::vector<std::unique_ptr<Resource>>
类可以在std::vector<Resource>
中正确存储,则资源管理器可以有Resource
作为数据成员,甚至更简单std::vector
。
然后,资源管理器可以向外部提供非拥有的观察指针,并且原始指针(或C ++引用)适用于这种情况。
当然,资源管理器的生命周期超过&#34;资源客户端的生命周期非常重要。
答案 2 :(得分:4)
所以我想我正在寻找的是一个可以理解的weak_ptr 无法转换为shared_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));
,但它需要更多的犯罪能量。