使用标准C++98/03对一个对象进行干净的分配和构造

Clean allocation and construction of one object with the standard C++98/03

本文关键字:分配 C++98 标准 一个对象      更新时间:2023-10-16

在我的代码中,我需要动态地分配和构造一个对象,并将指向它的指针推到向量中。有没有比下面的代码更干净的方法,而不使用所有那些丑陋的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是一个向量。

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

  • 对象将没有catch块的隐含上下文,即它需要传递必要的信息
  • 析构函数总是被调用的,也就是说,一旦主操作成功,就必须发出信号表明它确实需要做任何事情

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

一般来说,使用RAII是进行各种隐式撤销的方法,甚至与异常无关:!对于任何非常琐碎的代码,最终都会有人出现并从函数中返回。创建RAII类可能需要更多的前期工作,但我发现它极大地使我摆脱了与业务逻辑混淆的技术工作。此外,我的许多类最初都是RAII类,但后来变成了封装用于访问"资源"逻辑的功能的类。