使用标准C ++ 98/03清除分配和构造一个对象

时间:2012-03-17 17:24:29

标签: c++

在我的代码中,我需要动态分配和构造一个对象,并将指针推送到一个向量中。没有使用所有那些丑陋的try-catch块,有没有比下面的代码更简洁的方法?我不能使用非标准库。没有C ++ 11。我只有标准的C ++ 98/03。

void insert() {
            //...do something...
            MyType* obj = 0;
            try {
                obj = alloc.allocate(1); // yes, even the allocation must be inside one try-catch in my case, since I need to undo something
                alloc.construct(obj, default_obj);
                try {
                    v.push_back(obj);
                } catch (...) {
                    alloc.destroy(obj);
                    throw;
                }
            } catch (...) {
                //..undo something..
                if (obj)
                    alloc.deallocate(obj, 1);
                throw;
            }
}

编辑: alloc是一个在某处作为参数传递的分配器,以避免原始的new / delete。 v是一个向量。

1 个答案:

答案 0 :(得分:4)

显而易见的解决方案是使用自定义RAII类:带有rethrow的try / catch块等同于析构函数执行相同的清理,尽管有两个可管理的警告(除非以某种方式使用异常类型):

  • 该对象不具有catch-block的隐式上下文,即它需要传递必要的信息
  • 总是调用析构函数,即必须在主操作成功后发出需要执行任何操作的信号

由于你没有说明你还需要清理什么,除了在析构函数中执行此操作之外,我无法评论如何最好地解决这个问题。对于分配器使用,我实际上会创建一个自定义智能指针,它将构造函数参数和分配器作为其自身构造函数的参数(是的,具有可变参数和完美转发不可用这有点烦人但可行:我做了类似这样的事情比一次)。智能piinter实际上也会捆绑分配器,以便稍后使用正确的分配器处理解除分配。由于移动语义基本上不能在没有右值引用的情况下正确完成,因此智能指针将使用引用计数。

通常,使用RAII是各种隐式撤消的方式,甚至独立于异常:!对于任何重要的代码,最终有人出现并且从函数中过早地返回。创建RAII课程可能需要更多的前期工作,但我发现它极大地让我从技术工作中脱离了业务逻辑。此外,我已经开始使用许多类作为RAII类,但是变成了封装用于访问“资源”逻辑的功能的类。