最后在C++中

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)
  1. 没有异常抛出对象 - > NoException - >对象已清理
  2. 对象抛出异常 - > Handled - > NoException - >对象清理完毕
  3. 对象抛出的异常 - >抛出 - >异常 - >对象清理 - >抛出

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)

  • 不要寻找"正常的指针解决方案",如果你的意思是你想要避免RAII.如果你正在追求"好方法",那么在C++中就是RAII.所以要么使用库中的智能指针,要么你不能这样做,那就自己编写. (2认同)

Ste*_*sop 5

如果由于某种奇怪的原因您无法访问标准库,那么很容易实现您需要的智能指针类型来处理资源。它可能看起来有点冗长,但它的代码比那些嵌套的 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”析构函数保证在这两种情况下都会执行(尽管如果程序终止则不会执行)。