我疯狂地在我的功能中重新创建一个小型垃圾收集系统吗?

时间:2009-07-30 15:41:05

标签: c++ garbage-collection

我有一些(C ++)函数,每个函数包含多个调用,在堆上创建相同基本类型的类似数组。在这些函数的不同点,我可能需要抛出异常。跟踪哪些数组已被删除是一件痛苦的事情,而且非常容易出错,因此我在考虑将数组指针添加到Set<ArrType*>,我可以在捕获异常时删除每个项目,例如这样:

try
{
   set<ArrType*> sHeap;
   ArrType* myArr = new ArrType[5];
   sHeap.Add(myArr);
   someExternalRoutine(myArr);
   ...
} 
catch(CString s)
{
   DeleteAllPointersInMyHeap(sHeap);
   throw(s);
}

感觉有点像添加本轮,但我无法解决这样一个事实,即几个外部调用中的任何一个都可能抛出异常,我需要明确删除分配到该点的所有指针。

这只是愚蠢吗?我应该在外部调用周围添加较小的try-catch块吗?我最终还是会删除一些删除A的列表;删除B;删除D;在每一个之后...

5 个答案:

答案 0 :(得分:19)

为什么不使用像boost::shared_array这样的智能指针或使用堆栈分配的std::vector?对于单个分配而不是数组分配,您可以使用boost::shared_ptr

这些为您实施RAII。即使您正在重新使用像RAII这样的概念,如果已经有一个满足您要求的具体实施,您仍然会重新发明轮子。

答案 1 :(得分:10)

您应该使用RAII技术。 您将销毁委托给您在堆栈上创建的另一个对象。

然后当该对象超出范围时,它将释放所有内容,无论它何时超出范围,即使有例外。

答案 2 :(得分:8)

而不是

try
{
   set<ArrType*> sHeap;
   ArrType* myArr = new ArrType[5];
   sHeap.Add(myArr);
   someExternalRoutine(myArr);
   ...
} 

你只需要:

{
   std::vector <ArrType> myArr(5);
   someExternalRoutine(myArr);
}

没有捕获块。所有分配和解除分配(无论是否抛出异常)都将为您处理 - 这是RAII。

答案 3 :(得分:2)

您不必依赖垃圾收集。

你有std :: auto_ptr提供类似指针的语法并包装一个动态分配的对象。当它被破坏时,它会自动销毁它指向的对象。

你可以为数组实现类似的东西。

答案 4 :(得分:2)

看起来你正在思考它。

而不是使用try {} catch {}使用RAII 有几种方法可以查看注释(似乎都是有效的)。

选项1:
如果您只需要一个固定的(或扩展的ArrType集) 寿命在函数结束时结束的地方

std::vector<ArrType>

选项2:
如果需要多个ArrType数组 寿命在函数结束时结束的地方

boost::ptr_vector<ArrType> 

当对象具有更长的使用寿命时,这也允许您从ptr_vector中删除数组。

关于try {} catch {}

的注释
  • 赶上参考
    • 如果按特定类型捕获,则可以对切片问题进行优化,因为派生类型是复制构造到catch表达式中定义的变量。
  • 喜欢通过const ref
  • 捕获
  • 当重新投掷使用时; (没有表达)
    • 这将重新抛出原始异常,而不是将新异常复制到异常处理机制在堆栈展开期间隐藏异常的位置。