简体   繁体   English

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

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

In my code I need to allocate and construct an object dynamically and push the pointer to it into a vector. 在我的代码中,我需要动态分配和构造一个对象,并将指针推送到一个向量中。 Is there a cleaner way to this than the code below without using all those ugly try-catch blocks? 没有使用所有那些丑陋的try-catch块,有没有比下面的代码更简洁的方法? I cannot use non-standard libraries. 我不能使用非标准库。 There is no C++11. 没有C ++ 11。 I only have the standard C++98/03. 我只有标准的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;
            }
}

EDIT: alloc is an allocator passed as argument somewhere to avoid raw new/delete. 编辑:alloc是一个作为参数传递的分配器,以避免原始的新/删除。 v is a vector. v是一个向量。

The obvious solution is to use custom RAII classes: a try/catch block with a rethrow is equivalent to a destructor doing the same clean-up although with two managable caveats (unless the exception type is used somehow): 显而易见的解决方案是使用自定义RAII类:带有重新抛出的try / catch块等同于析构函数执行相同的清理,尽管有两个可管理的警告(除非以某种方式使用异常类型):

  • the object won't have the implicit context of the catch-block ie it needs to get the necessary information passed 该对象将不具有catch-block的隐式上下文,即它需要传递必要的信息
  • the destructor is always called, ie it is necessary to signal that it does need to do anything once the main operation succeeded 总是调用析构函数,即必须在主操作成功后发出需要执行任何操作的信号

Since you didn't state what else you needed to clean-up I can't comment in how to best deal with this other than doing it in a destructor. 既然你没有说明你还需要清理什么,除了在析构函数中执行此操作之外,我无法评论如何最好地处理此问题。 For the allocator use I would actually create a custom smart pointer which takes the constructor arguments and the allocator as arguments to its own constructor (yes, with variadic and perfect forwarding unavailable this is a bit annoying but doable: I have done something like this more than once). 对于分配器使用,我实际上会创建一个自定义智能指针,它将构造函数参数和分配器作为其自己的构造函数的参数(是的,具有可变参数和完美转发不可用这有点烦人但可行:我做了类似这样的事情比一次)。 The smart piinter would actually bundle up the allocator as well for also dealing with the deallocation later using the correct allocator. 智能piinter实际上也会捆绑分配器,以便稍后使用正确的分配器处理解除分配。 Since move semantics essentially can't be done right without rvalue references the smart pointer would use reference counting. 由于移动语义基本上不能在没有右值引用的情况下正确完成,因此智能指针将使用引用计数。

Generally, using RAII is the way for all kinds of implicit undoing, even independent of exception:!for any mon-trivial code eventually someone comes along andprematurely returns from the function. 通常,使用RAII是各种隐式撤消的方式,甚至独立于异常:!对于任何重要的代码,最终有人出现并且从函数中过早地返回。 It may be a bit more up-front work to create RAII classes but I found that it dramatically releaves me from rather technical work mixed up with business logic. 创建RAII课程可能需要更多的前期工作,但我发现它极大地让我从技术工作中脱离了业务逻辑。 Also, many classes I have started their life as RAII classes but turned into classes encapsulating the functionality used to access the "resource's" logic. 此外,我已经开始使用许多类作为RAII类,但是转换为封装用于访问“资源”逻辑的功能的类。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM