我可以制作一个 unique_ptr 不获取其指向对象的所有权吗?
Posted
技术标签:
【中文标题】我可以制作一个 unique_ptr 不获取其指向对象的所有权吗?【英文标题】:Can I make a unique_ptr not to take the ownership of its pointed object? 【发布时间】:2013-10-16 14:25:19 【问题描述】:我有一个唯一指针向量。其中,我希望一个不占用其指向对象的所有权。怎么做?
vector<unique_ptr<int>> v;
v.push_back(make_unique<int>(10));
unique_ptr<int> p(new int(20)); // add it to v but keep p take the ownership.
问题来自以下案例。我有一个由 GUI 树小部件表示的树结构数据。父节点使用vector<unique_ptr<T>>
获取其子节点的所有权。但有一个例外。我有一个常见的单例数据,并希望将其附加到树中以获取友好的用户界面。存在冲突,因为 sigleton 也取得了所有权。使用 share_ptr 可以,但会牺牲一些性能。
感谢大家的回答、cmets 和建议。这可能是一个设计缺陷。也许我需要一个带有vector<unique_ptr<T>>
(对于其他人)和shared_ptr
的特殊父节点的新类,甚至是一个原始指针(对于单例)来处理异常。
【问题讨论】:
你为什么要这样做?动机是什么?使用原始指针? 你不能——这个名字是唯一的指针是有原因的。 为什么不使用shared_ptr
和weak_ptr
?
我不会卷入整个“单身狗烂”的圣战(不只是提及),但我仍然想知道你为什么想要vector<unique_ptr>
如果您认为该资源应该归其他人所有?
XY-Problem 警报。请说明你真正想做什么,而不是你想怎么做
【参考方案1】:
你想要一个不拥有它所指向的东西的unique_ptr
。
这些目标是相互矛盾的。 unique_ptr
的全部意义在于拥有它管理的资源。
在这里之后我很难推断出你是什么真正,因为你没有说你想要做什么 - 只是如何您正在尝试这样做。为什么你想要一个不拥有资源的unique_ptr
?
也许您真正追求的是shared_ptr
,以便shared_ptr
的多个实例可以共享同一个对象的所有权。
再一次,也许您所追求的是weak_ptr
,它本身并不(完全)“拥有”一个指针,直到它被提升为shared_ptr
。
阅读您的编辑后,我可能会预感到您在这里真正想要的是什么。你已经说过你希望你的单例对象真正拥有资源,但你仍然希望你的vector
有一个智能指针。也许您真正想要的是让vector
拥有一个不拥有对象本身的智能指针,但如果实际拥有的对象被销毁,它将变得无效或“无效”。
如果是这样,那么你的单例应该有一个shared_ptr
,向量应该是一个vector<weak_ptr>
。当您需要通过vector
实际获取对象时,您将调用lock
以提取shared_ptr
- 检查来自lock
的返回以确保weak_ptr
没有过期。您也可以通过调用expired
来检查shared_ptr
是否已过期而不锁定它。
【讨论】:
+1,只是小评论。你不应该在lock()
之前测试expired()
;这是没有意义的,因为无论如何你都必须测试lock()
的结果(理论上它可能会在调用expired()
和lock()
之间过期)。【参考方案2】:
您不能使用普通的 unique_ptr<int>
来执行此操作 - 名称是 unique 指针,这是有原因的。
如果你真的很想这样做(但我 99.99% 确定这只是糟糕设计的征兆),你可以使用自定义删除器:
template <class T>
struct WeirdDeleter
bool owning;
explicit WeirdDeleter(bool owning = true) : owning(owning)
void operator() (const T *p) const
if (owning) delete p;
;
//Usage:
vector<unique_ptr<int, WeirdDeleter<int>>> v;
unqiue_ptr<int, WeirdDeleter<int>> p(new int(10));
v.push_back(std::move(p));
int *q = new int(20);
v.push_back(unique_ptr<int, WeirdDeleter<int>>(q, WeirdDeleter(false));
(我不知道关于删除器的建议make_unique
接口,所以我没有使用它;它仍然可以使用)。
重申一下,我认为这样做是一个坏主意(tm),但如果你真的想这样做,应该是这样。
【讨论】:
聪明,但我觉得有点太聪明了。 @JohnDibling 我努力表达我会避免使用它,但我知道有时情况(或老板)需要采取绝望的措施。 不,我明白了。我没有投反对票,实际上我 +1 了。我想我真的只是在强调你断言这是一个坏主意。 @JohnDibling 是的,我也是这么理解的。【参考方案3】:unique_ptr
用于它具有独占所有权的确切用例。所以你不能用它来指向某物并且不取得所有权。
解决方案很简单:改用shared_ptr
。它没有独占所有权,相反,它指向同一个对象的所有实例都将共享所有权;只有当最后一个超出范围时,才会删除该对象。
如果您想要一个不影响所有权的指针,请查看weak_ptr
。
【讨论】:
Ashared_ptr
仍然拥有该资源。请编辑您的答案,以便我能更好地理解您在这里的意思。
我有。现在好多了?但我猜你的答案还是好一点;)
这样更好,谢谢。我怀疑shared_ptr
仍然不是 OP 所追求的,但无论如何 +1。以上是关于我可以制作一个 unique_ptr 不获取其指向对象的所有权吗?的主要内容,如果未能解决你的问题,请参考以下文章
如何在容器,ptrs和对象不可修改的情况下传递unique_ptrs容器?