Boost shared_ptr use_count函数

时间:2010-05-28 13:40:42

标签: c++ boost shared-ptr

我的申请问题如下 -

我有一个庞大的结构foo。因为它们很大并且出于内存管理的原因,我们不希望在完成数据处理时删除它们。

我们将它们存储在std::vector<boost::shared_ptr<foo>>.

我的问题与知道所有处理何时完成有关。第一个决定是我们不希望任何其他应用程序代码在结构中标记完整标志,因为程序中有多个执行路径,我们无法预测哪一个是最后一个。

因此,在我们的实现中,一旦处理完成,我们将删除boost::shared_ptr<foo>>的所有副本,但向量中的副本除外。这会将shared_ptr中的引用计数器丢弃为1.使用shared_ptr.use_count()来查看它是否等于1是否可行,以了解我的应用程序的所有其他部分何时完成了数据。

我提出这个问题的另一个原因是共享指针shared_ptr上的boost文档建议不要将“use_count”用于生产代码。


编辑 - 我没有说的是,当我们需要一个新的foo时,我们将扫描foo指针的向量,寻找当前没有使用的foo,并使用该foo进行下一轮处理。这就是为什么我认为使用1的引用计数器将是一种安全的方法来确保不再使用这个特定的foo对象。

5 个答案:

答案 0 :(得分:4)

我的直接反应(我承认,不过是这个)是听起来你正试图获得某种池分配器的效果。您可能最好重载operator newoperator delete以获得更直接的效果。有了类似的东西,你可以像正常一样使用shared_ptr,而你想要延迟的其他工作将在operator delete中为该类处理。

这留下了一个更基本的问题:你真正想要实现的目标是什么?从内存管理的角度来看,一个共同的愿望是一次为大量对象分配内存,并且在整个块为空之后,立即释放整个块。如果您尝试在该订单上执行某些操作,则通过重载newdelete而不是通过使用shared_ptr的{​​{1}}来玩游戏,几乎可以肯定更容易实现。< / p>

修改:根据您的评论,重载use_countnew类似于正确的做法。如果有的话,集成到现有代码可能会更容易;事实上,你经常可以完全透明地完成它。

分配器的一般想法与您在编辑过的问题中概述的基本相同:有一个结构(位图和链接列表都是常见的)来跟踪您的自由对象。当delete需要分配一个对象时,它可以扫描位向量或查看自由对象链表的头部,并返回其地址。

这是链接列表可以很好地运行的一种情况 - 您(通常)不必担心内存使用情况,因为您将链接存储在自由对象中,并且您(几乎)永远不必走这个列表,因为当你需要分配一个对象时,你只需抓住列表中的第一个项目。

这种事情在小型对象中尤为常见,因此您可能希望查看其小型对象分配器上的 Modern C ++ Design 章节(以及Andrei Alexandrescu撰写的一篇或两篇文章)他对如何做这类事情的新想法)。还有Boost :: pool分配器,它通常至少有点类似。

答案 1 :(得分:3)

如果您想知道使用次数是否为1,请使用unique()成员函数。

答案 2 :(得分:2)

我想说你的应用程序应该有一些方法可以消除应用程序其他部分对Foo的所有引用,并且应该使用该方法而不是检查use_count()。此外,如果use_count()大于1,您的计划会做什么?您不应该依赖shared_ptr的功能来消除所有引用,您的应用程序架构应该能够消除引用。在将其从向量中移除之前作为最终检查,您可以assert(unique())验证它是否真正被释放。

答案 3 :(得分:2)

我认为您可以使用shared_ptr的自定义删除功能在最后一个副本发布时调用特定功能。这样,您根本就没有使用use_count

您需要在shared_ptr中保留vector的副本以外的其他内容,以便shared_ptr仅跟踪未完成的处理。

Boost在shared_ptr文档中有several examples of custom deleters

答案 4 :(得分:0)

我建议不要尝试使用shared_ptr的use_count来跟踪,而是实现自己的使用计数器可能更好。这样你就可以完全控制它而不是使用shared_ptr,正如你正确建议的那样,不推荐使用它。您还可以预先设置自己的计数器,以允许您知道需要对数据执行操作的线程数,而不是依赖它们在开始时初始化以获取结构副本。