使用标准C++98/03对一个对象进行干净的分配和构造
Clean allocation and construction of one object with the standard C++98/03
在我的代码中,我需要动态地分配和构造一个对象,并将指向它的指针推到向量中。有没有比下面的代码更干净的方法,而不使用所有那些丑陋的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类,但后来变成了封装用于访问"资源"逻辑的功能的类。
相关文章:
- 将数组的地址分配给变量并删除
- vector.resize()中的分配错误
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- Win32编译器选项和内存分配
- 函数中堆分配的效果与缺少堆分配的情况
- 使用动态分配的数组会导致代码分析发出虚假的C6386缓冲区溢出警告
- 多个文件的内存分配错误"在抛出 'std :: bad_alloc' what (): std :: bad_alloc 的实例后终止调用" [C++]
- 获取字符串的长度并将其分配给数组
- 将地址分配给本地指针后,公共对象的变量将消失
- 递归模板化函数不能分配给具有常量限定类型"const tt &"的变量"state"
- 有没有一种方法可以使用placement new将堆叠对象分配给分配的内存
- 我在二维向量中是否正确分配了内存
- 正在尝试重载二进制搜索树分配运算符
- GlobalAlloc而不是其他分配方法
- 自定义先决条件对移动分配运算符有效吗
- 我可以重新分配/覆盖std::字符串吗
- 在c++中使用动态分配的问题
- 当一个新对象被分配到它的地址时,对象是否必须被销毁
- 为什么我可以使用比分配的内存更多的内存
- 使用标准C++98/03对一个对象进行干净的分配和构造