Tam*_*man 11 c++ exception finally try-catch throw
这是在标准C++中实现类似Last的行为的好方法吗?(没有特殊指针)
class Exception : public Exception
{ public: virtual bool isException() { return true; } };
class NoException : public Exception
{ public: bool isException() { return false; } };
Object *myObject = 0;
try
{
// OBJECT CREATION AND PROCESSING
try
{
myObject = new Object();
// Do something with myObject.
}
// EXCEPTION HANDLING
catch (Exception &e)
{
// When there is an excepion, handle or throw,
// else NoException will be thrown.
}
throw NoException();
}
// CLEAN UP
catch (Exception &e)
{
delete myObject;
if (e.isException()) throw e;
}
Run Code Online (Sandbox Code Playgroud)
Dav*_*man 28
标准答案是使用资源分配 - 初始化缩写RAII的一些变体.基本上你构造了一个变量,它与最终块之前的块内部的块具有相同的范围,然后在对象析构函数内的finally块中进行工作.
try {
// Some work
}
finally {
// Cleanup code
}
Run Code Online (Sandbox Code Playgroud)
变
class Cleanup
{
public:
~Cleanup()
{
// Cleanup code
}
}
Cleanup cleanupObj;
// Some work.
Run Code Online (Sandbox Code Playgroud)
这看起来非常不方便,但通常会有一个预先存在的对象可以为您清理.在您的情况下,看起来您想要破坏finally块中的对象,这意味着智能或自动指针将执行您想要的操作:
std::unique_ptr<Object> obj(new Object());
Run Code Online (Sandbox Code Playgroud)
无论抛出哪个异常,对象都将被破坏.回到RAII,在这种情况下,资源分配是为Object分配内存并构造它,初始化是auto_ptr的初始化.
Joh*_*itb 11
不.构建最终方式的标准方法是分离关注点(http://en.wikipedia.org/wiki/Separation_of_concerns)并使try块中使用的对象自动释放其析构函数中的资源(称为"范围限制资源管理").由于析构函数确定性地运行,与Java不同,您可以依赖它们来安全地进行清理.这样,获取资源的对象也将清理资源.
一种特殊的方法是动态内存分配.由于您是获取资源的人,因此您必须再次清理.在这里,可以使用智能指针.
try {
// auto_ptr will release the memory safely upon an exception or normal
// flow out of the block. Notice we use the "const auto_ptr idiom".
// http://www.gotw.ca/publications/using_auto_ptr_effectively.htm
std::auto_ptr<A> const aptr(new A);
}
// catch...
Run Code Online (Sandbox Code Playgroud)
如果由于某种奇怪的原因您无法访问标准库,那么很容易实现您需要的智能指针类型来处理资源。它可能看起来有点冗长,但它的代码比那些嵌套的 try/catch 块少,而且您只需定义此模板一次,而不是每个需要管理的资源定义一次:
template<typename T>
struct MyDeletable {
explicit MyDeletable(T *ptr) : ptr_(ptr) { }
~MyDeleteable() { delete ptr_; }
private:
T *ptr_;
MyDeletable(const MyDeletable &);
MyDeletable &operator=(const MyDeletable &);
};
void myfunction() {
// it's generally recommended that these two be done on one line.
// But it's possible to overdo that, and accidentally write
// exception-unsafe code if there are multiple parameters involved.
// So by all means make it a one-liner, but never forget that there are
// two distinct steps, and the second one must be nothrow.
Object *myObject = new Object();
MyDeletable<Object> deleter(myObject);
// do something with my object
return;
}
Run Code Online (Sandbox Code Playgroud)
当然,如果您这样做,然后在其余代码中使用 RAII,您最终将需要标准和增强智能指针类型的所有功能。但这只是一个开始,并且做我认为你想要的事情。
try ... catch 方法在面对维护编程时可能不会很好地工作。CLEAN UP 块不保证被执行:例如,如果“做某事”代码提前返回,或者以某种方式抛出一些不是异常的东西。另一方面,我的代码中的“deleter”析构函数保证在这两种情况下都会执行(尽管如果程序终止则不会执行)。
| 归档时间: |
|
| 查看次数: |
19065 次 |
| 最近记录: |