C++ 我应该在非主要容器上使用共享\u ptr还是弱\u ptr?

C++ 我应该在非主要容器上使用共享\u ptr还是弱\u ptr?,c++,c++11,smart-pointers,C++,C++11,Smart Pointers,我有两个std容器。它们都具有指向相同数据结构的指针。第一个包含所有数据,第二个仅包含部分相同数据。我应该在第二个容器上使用shared\u ptr还是weak\u ptr 首先,当我阅读参考资料时,我想到在第一个集合中使用unique\ptr。我的第一个收藏包含所有数据,它是唯一“拥有”的。这意味着如果数据不存在,则应将其删除。但是当我尝试创建第二个集合时,我不知道该怎么做。我创建了一个唯一的指针,但现在我需要另一个指向同一元素的指针来破坏唯一性,但实际上真正的所有者不是新指针。所以我明白(我

我有两个std容器。它们都具有指向相同数据结构的指针。第一个包含所有数据,第二个仅包含部分相同数据。我应该在第二个容器上使用
shared\u ptr
还是
weak\u ptr

首先,当我阅读参考资料时,我想到在第一个集合中使用
unique\ptr
。我的第一个收藏包含所有数据,它是唯一“拥有”的。这意味着如果数据不存在,则应将其删除。但是当我尝试创建第二个集合时,我不知道该怎么做。我创建了一个唯一的指针,但现在我需要另一个指向同一元素的指针来破坏唯一性,但实际上真正的所有者不是新指针。所以我明白(我希望我没有错)唯一性是在到达元素的路上,而不是(例如)删除它的可能性。所以,
shared\u ptr
。我第一次收藏的时候就有了。但是现在第二个出现了,我想在这里也使用
shared\u ptr
。访问相同数据的方法可以是两种,因此所有者是两种。但在我的例子中,数据总是在第二个之前被删除。如果我使用
弱\u ptr
,所有者的数量不会增加。在这两种情况下,当第一个集合需要时,元素将被删除。最后,我使用了
shared\u ptr
,因为使用
weak\u ptr
时,我需要
lock()。但是我应该用什么呢?

你说的“每一行代码”是什么意思?通常的模式如下:

if (auto p = wp.lock()) {
    // p is a shared_ptr; use it as often as you need within the block.
}
如果您有一个拥有者容器和一个引用容器,如果所有者销毁了仲裁人,那么
共享的\u ptr
/
弱的\u ptr
就是正确的选择。

好问题

根据经验,我发现使用
共享ptr
/
弱ptr
,甚至扩展使用
共享ptr
,通常会导致某种大的模糊设计

在过去,一些人主张共享被认为是有害的。因为它使所有权浮动。所有权应该通过设计来明确。我不确定我是否愿意采纳这一建议并加以提倡;但为了回答这个问题,我肯定会在这里重复一遍

也可以考虑使用<代码> SydDypPT/<代码>到处都是与使用垃圾收集相同。这只是引用计数,但最终的行为是相同的。只有性能不太好,这在过去已经被证明,一个好的垃圾收集引擎比任何东西都要快。(这肯定是因为

shared\u ptr
中需要CPU原子指令和屏障,但我推测。)

也许你应该考虑迁移到一个非常好的垃圾收集语言/平台,比如C.O.N.NET 4?/P> 否则,如果不使用直接指针模式,而是使用标识符,您可以创建一个管理器模式,在这个管理器中,您的2个索引数据结构是私有的。客户只能通过管理者的API查看和使用标识符(
int
uint64\u t
?,由您自行决定)

我发现这种方法的问题是需要在管理器中重复操作对象的整个API。这是痛苦的,不尊重他人

否则,您是否考虑过可能您的数据结构并非天生必需的?
我的意思是,不管怎样,当存储指针时,索引数据结构往往不会太大。它只是
N*sizeof(ptr\u t)
,而不是
N*sizeof(value\u t)
。这突然使得
std::vector
在所有情况下都成为一个优秀的候选者。我的意思是向量已经是几乎所有用途的最佳数据结构

如果您的向量只包含指针,请帮自己一个忙,通过使用
boost::ptr_向量
来减轻
shared_ptr
开销


我希望我带来了一些观点。

听起来你不需要
std::shared\u ptr
,因为你的数据是在一个地方拥有的

我建议在拥有的容器中使用
std::unique_ptr
,然后简单地将原始指针放在第二个和后续容器中

这是因为您永远不会删除原始指针,但它们指向的数据仍由智能指针管理,因此在您不再需要它时将被释放


尽管有一些坏消息,但原始指针在用作非所有者访问由其他实体拥有的数据时是非常值得尊敬的,这些实体将在适当的时候删除该数据。

您没有给出关键信息,即您是否可以保证两个集合具有相同的生存期。如果可以保证两个集合具有相同的生存期,那么对拥有所有内容的集合使用unique_ptr,对另一个集合使用原始指针(如@Galik所建议的)是理想的

如果无法保证这两个生命周期匹配,那么您是为这两个生命周期选择shared_ptr,还是为第一个生命周期选择shared_ptr,为第二个生命周期选择weak,取决于您希望销毁对象的时间。听起来只有第一个集合才是真正的所有者,所以您需要弱指针

然而,我强烈建议您坚持第一种方法。避免共享ptr和弱ptr更干净。危险在于,如果两个集合具有不同的生存期,则第一个集合可能会在第二个集合之前被销毁(只是一个放错位置的括号),然后当第二个集合尝试访问时,它会有悬空指针。当然,您可以简单地小心处理变量,但是保证两个独立的局部变量始终具有相同的生命周期是非常容易搞糟的

如果你