0

在我最近的 C++ 内存管理工作中,我一直在搞乱使用智能指针。部分原因是我使用一系列映射将字符串与一个类(称为 IBlockInput)联系起来,并将该类与“上下文”内的当前值联系起来。我看到两个选项,但都有相同的问题:

选项1:类的当前值存储在类内部,按上下文排序

选项 2:类的当前值存储在上下文中,按类排序

这里的问题是任何一个对象都可能先于另一个对象死亡。一个上下文可能在所有输入保留时被销毁,或者一个输入可能在上下文保留时被销毁。当一个人死亡时,需要为它释放资源。到目前为止我所拥有的是(使用选项 2):

std::map<std::string, boost::weak_ptr<IBlockInput> > inputs;
std::map<boost::weak_ptr<IBlockInput>, boost::shared_ptr<std::vector<double> > > inputValues;

它们需要像这样分开的原因是其他类(IOutputBlocks)需要根据它们的指针访问和设置 IInputBlocks 的值。

我对此有几个问题:

问题 1:我可以像普通贴图一样访问 inputValues 贴图并只传递指针(而不是 boost::shared_ptr/boost::weak_ptr...T*)来访问它吗?如果这是实际的方法,我也可以使用weak_ptrs 或shared_ptrs

问题 2:如果需要,我正在使用弱指针让对象死掉(如果我在上面执行选项 1,我将不得不使用指向上下文的弱指针)。如果弱指针过期并且我尝试在地图中访问它会发生什么?它指向的数据是否已经丢失了,还是仍然可以使用原始指针?

问题 3:也许更好的方法是使用原始指针作为键/值,然后使用弱指针(用于各种实时检查)进行补充映射,如下所示:

std::map<std::string, IBlockInput*> inputs;
std::map<IBlockInput*, boost::shared_ptr<std::vector<double> > inputValues;
std::map<IBlockInput*, boost::weak_ptr<IBlockInput> > pointerCache;

然后我可以使用 来做一个“实时检查” pointerCache,看看我是否应该保持双打向量活着并以这种方式管理内存。注意:输入向量相对频繁地刷新。

推荐的做法是什么?一般来说,我对提升和使用智能指针非常陌生(过去几个月我在工作中一直被 C# 宠爱,不必担心这种事情)。

4

1 回答 1

0

std::map<boost::weak_ptr<IBlockInput>, boost::shared_ptr<std::vector<double> > > inputValues; - 这是不好的。当 aweak_ptr死亡时,它将比较等于nullptr,并且它的顺序不保持。你会得到未定义的行为(实际上,无限循环和崩溃)

小心你在std::maps 中使用什么键。

由于 ABA 问题,使用可能被释放的原始指针是不好的,其中一个有效的指针变得无效,然后分配一个与其相等的新指针。(有利用实现细节make_shared使这种事情在实践中发挥作用,但那是混乱和危险的)

您可能需要某种双重间接,其中您有指向指针的指针。我称它们为把手。句柄到期的内部指针导致它在地图中注销句柄,并且当它超出每个地图时,它会自行销毁。我不知道它是否会起作用,但它可能会。我怀疑它首先需要一些摆弄。

句柄将按其(外部)指针值排序,因此将保持排序。要确定句柄是否有效,您必须同时检查外部和内部指针的有效性(因此非空句柄可能对“取消引用”无效)。

但我想不出办法让这个干净。

于 2012-12-10T04:36:24.550 回答