在我最新的C ++内存管理方面,我一直在使用智能指针。部分原因是我使用一系列映射将字符串绑定到类(称为IBlockInput),将类绑定到“context”中的当前值。我看到两个选项,但两者都有同样的问题:
选项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#的呵护,不必担心关于这种事情。)
答案 0 :(得分:0)
std::map<boost::weak_ptr<IBlockInput>, boost::shared_ptr<std::vector<double> > > inputValues;
- 这很糟糕。当weak_ptr
死亡时,它将等于nullptr
,并且不会维持其顺序。您将获得未定义的行为(实际上,无限循环和崩溃)
请注意std::map
s。
使用可能被解除分配的原始指针是不好的,因为ABA问题,有效指针变为无效,然后新指针被分配等于它。 (正在利用make_shared
的实施细节来使这种事情在实践中发挥作用,但这是混乱和危险的)
你可能需要某种双重间接,你可以使用与指针相同的指针。我会称他们为句柄。句柄到期的内部指针使它取消注册地图中的句柄,当它超出每个地图时它会自行销毁。我不知道它是否会起作用,但它可能会起作用。我怀疑它首先需要一些摆弄。
句柄将按其(外部)指针值排序,因此将保持排序。要确定句柄是否有效,您必须同时检查外部和内部指针的有效性(因此非空句柄可能对“取消引用”无效)。
但我想不出办法让这个干净。